tr macros now documented
This commit is contained in:
parent
6d94e45902
commit
92b449562e
14 changed files with 332 additions and 18 deletions
|
|
@ -146,7 +146,7 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
|
||||||
case opr
|
case opr
|
||||||
of "|": result = matchChoice(c, p, n)
|
of "|": result = matchChoice(c, p, n)
|
||||||
of "*": result = matchNested(c, p, n, rpn=false)
|
of "*": result = matchNested(c, p, n, rpn=false)
|
||||||
of "*|": result = matchNested(c, p, n, rpn=true)
|
of "**": result = matchNested(c, p, n, rpn=true)
|
||||||
of "~": result = not matches(c, p.sons[1], n)
|
of "~": result = not matches(c, p.sons[1], n)
|
||||||
else: InternalError(p.info, "invalid pattern")
|
else: InternalError(p.info, "invalid pattern")
|
||||||
# template {add(a, `&` * b)}(a: string{noalias}, b: varargs[string]) =
|
# template {add(a, `&` * b)}(a: string{noalias}, b: varargs[string]) =
|
||||||
|
|
|
||||||
|
|
@ -491,7 +491,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
# we interpret `*` and `|` only as pattern operators if they occur in
|
# we interpret `*` and `|` only as pattern operators if they occur in
|
||||||
# infix notation, so that '`*`(a, b)' can be used for verbatim matching:
|
# infix notation, so that '`*`(a, b)' can be used for verbatim matching:
|
||||||
let opr = n.sons[0]
|
let opr = n.sons[0]
|
||||||
if opr.ident.s == "*" or opr.ident.s == "*|":
|
if opr.ident.s == "*" or opr.ident.s == "**":
|
||||||
result = newNodeI(nkPattern, n.info, n.len)
|
result = newNodeI(nkPattern, n.info, n.len)
|
||||||
result.sons[0] = opr
|
result.sons[0] = opr
|
||||||
result.sons[1] = semPatternBody(c, n.sons[1])
|
result.sons[1] = semPatternBody(c, n.sons[1])
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ Comex
|
||||||
Eric Doughty-Papassideris
|
Eric Doughty-Papassideris
|
||||||
Simon Hafner
|
Simon Hafner
|
||||||
Keita Haga
|
Keita Haga
|
||||||
|
Grzegorz Adam Hankiewicz
|
||||||
Philippe Lhoste
|
Philippe Lhoste
|
||||||
Zahary Karadjov
|
Zahary Karadjov
|
||||||
Mario Ray Mahardhika
|
Mario Ray Mahardhika
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,10 @@ The documentation consists of several documents:
|
||||||
| The Nimrod compiler supports source code filters as a simple yet powerful
|
| The Nimrod compiler supports source code filters as a simple yet powerful
|
||||||
builtin templating system.
|
builtin templating system.
|
||||||
|
|
||||||
|
- | `Term rewriting macros <trmacros.html>`_
|
||||||
|
| Term rewriting macros enhance the compilation process with user defined
|
||||||
|
optimizations.
|
||||||
|
|
||||||
- | `Internal documentation <intern.html>`_
|
- | `Internal documentation <intern.html>`_
|
||||||
| The internal documentation describes how the compiler is implemented. Read
|
| The internal documentation describes how the compiler is implemented. Read
|
||||||
this if you want to hack the compiler.
|
this if you want to hack the compiler.
|
||||||
|
|
|
||||||
|
|
@ -3663,6 +3663,8 @@ hints on|off Turns the hint messages of the compiler
|
||||||
on or off.
|
on or off.
|
||||||
optimization none|speed|size Optimize the code for speed or size, or
|
optimization none|speed|size Optimize the code for speed or size, or
|
||||||
disable optimization.
|
disable optimization.
|
||||||
|
patterns on|off Turns the term rewriting templates/macros
|
||||||
|
on or off.
|
||||||
callconv cdecl|... Specifies the default calling convention for
|
callconv cdecl|... Specifies the default calling convention for
|
||||||
all procedures (and procedure types) that
|
all procedures (and procedure types) that
|
||||||
follow.
|
follow.
|
||||||
|
|
|
||||||
288
doc/trmacros.txt
Normal file
288
doc/trmacros.txt
Normal file
|
|
@ -0,0 +1,288 @@
|
||||||
|
=========================================================
|
||||||
|
Term rewriting macros for Nimrod
|
||||||
|
=========================================================
|
||||||
|
|
||||||
|
:Author: Andreas Rumpf
|
||||||
|
|
||||||
|
Term rewriting macros are macros or templates that have not only a *name* but
|
||||||
|
also a *pattern* that is searched for after the semantic checking phase of
|
||||||
|
the compiler: This means they provide an easy way to enhance the compilation
|
||||||
|
pipeline with user defined optimizations:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template optMul{`*`(a, 2)}(a: int): int = a+a
|
||||||
|
|
||||||
|
let x = 3
|
||||||
|
echo x * 2
|
||||||
|
|
||||||
|
The compiler now rewrites ``x * 2`` as ``x + x``. The code inside the
|
||||||
|
curlies is the pattern to match against. The operators ``*``, ``**``,
|
||||||
|
``|``, ``~`` have a special meaning in patterns if they are written in infix
|
||||||
|
notation, so to match verbatim against ``*`` the ordinary function call syntax
|
||||||
|
needs to be used.
|
||||||
|
|
||||||
|
|
||||||
|
Unfortunately optimizations are hard to get right and even the tiny example
|
||||||
|
is **wrong**:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template optMul{`*`(a, 2)}(a: int): int = a+a
|
||||||
|
|
||||||
|
proc f(): int =
|
||||||
|
echo "side effect!"
|
||||||
|
result = 55
|
||||||
|
|
||||||
|
echo f() * 2
|
||||||
|
|
||||||
|
We cannot duplicate 'a' if it denotes an expression that has a side effect!
|
||||||
|
Fortunately Nimrod supports side effect analysis:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template optMul{`*`(a, 2)}(a: int{noSideEffect}): int = a+a
|
||||||
|
|
||||||
|
proc f(): int =
|
||||||
|
echo "side effect!"
|
||||||
|
result = 55
|
||||||
|
|
||||||
|
echo f() * 2 # and still optimized ;-)
|
||||||
|
|
||||||
|
The reason is that the compiler does not consider 'echo' to have side effects
|
||||||
|
for debugging convenience (this is comparable to Haskell's ``UnsafeIO`` monad).
|
||||||
|
So lets try it with a "real" side effect:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template optMul{`*`(a, 2)}(a: int{noSideEffect}): int = a+a
|
||||||
|
|
||||||
|
proc f(): int =
|
||||||
|
writeln stdout, "side effect!"
|
||||||
|
result = 55
|
||||||
|
|
||||||
|
echo f() * 2 # not optimized ;-)
|
||||||
|
|
||||||
|
So what about ``2 * a``? We should tell the compiler ``*`` is commutative. We
|
||||||
|
cannot really do that however as the following code only swaps arguments
|
||||||
|
blindly:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template mulIsCommutative{`*`(a, b)}(a, b: int): int = b*a
|
||||||
|
|
||||||
|
What optimizers really need to do is a *canonicalization*:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template canonMul{`*`(a, b)}(a: int{lit}, b: int): int = b*a
|
||||||
|
|
||||||
|
The ``int{lit}`` parameter pattern matches against an expression of
|
||||||
|
type ``int``, but only if it's a literal.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Parameter constraints
|
||||||
|
=====================
|
||||||
|
|
||||||
|
The parameter constraint expression can use the operators ``|`` (or),
|
||||||
|
``&`` (and) and ``~`` (not) and the following predicates:
|
||||||
|
|
||||||
|
=================== =====================================================
|
||||||
|
Predicate Meaning
|
||||||
|
=================== =====================================================
|
||||||
|
``atom`` The matching node has no children.
|
||||||
|
``lit`` The matching node is a literal like "abc", 12.
|
||||||
|
``sym`` The matching node must be a symbol (a bound
|
||||||
|
identifier).
|
||||||
|
``ident`` The matching node must be an identifier (an unbound
|
||||||
|
identifier).
|
||||||
|
``call`` The matching AST must be a call/apply expression.
|
||||||
|
``lvalue`` The matching AST must be an lvalue.
|
||||||
|
``sideeffect`` The matching AST must have a side effect.
|
||||||
|
``nosideeffect`` The matching AST must have no side effect.
|
||||||
|
``param`` A symbol which is a parameter.
|
||||||
|
``genericparam`` A symbol which is a generic parameter.
|
||||||
|
``module`` A symbol which is a module.
|
||||||
|
``type`` A symbol which is a type.
|
||||||
|
``var`` A symbol which is a variable.
|
||||||
|
``let`` A symbol which is a ``let`` variable.
|
||||||
|
``const`` A symbol which is a constant.
|
||||||
|
``result`` The special ``result`` variable.
|
||||||
|
``proc`` A symbol which is a proc.
|
||||||
|
``method`` A symbol which is a method.
|
||||||
|
``iterator`` A symbol which is an iterator.
|
||||||
|
``converter`` A symbol which is a converter.
|
||||||
|
``macro`` A symbol which is a macro.
|
||||||
|
``template`` A symbol which is a template.
|
||||||
|
``field`` A symbol which is a field in a tuple or an object.
|
||||||
|
``enumfield`` A symbol which is a field in an enumeration.
|
||||||
|
``forvar`` A for loop variable.
|
||||||
|
``label`` A label (used in ``block`` statements).
|
||||||
|
``nk*`` The matching AST must have the specified kind.
|
||||||
|
(Example: ``nkIfStmt`` denotes an ``if`` statement.)
|
||||||
|
``alias`` States that the marked parameter needs to alias
|
||||||
|
with *some* other parameter.
|
||||||
|
``noalias`` States that *every* other parameter must not alias
|
||||||
|
with the marked parameter.
|
||||||
|
=================== =====================================================
|
||||||
|
|
||||||
|
The ``alias`` and ``noalias`` predicates refer not only to the matching AST,
|
||||||
|
but also to every other bound parameter; syntactially they need to occur after
|
||||||
|
the ordinary AST predicates:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template ex{a = b + c}(a: int{noalias}, b, c: int) =
|
||||||
|
# this transformation is only valid if 'b' and 'c' do not alias 'a':
|
||||||
|
a = b
|
||||||
|
inc a, b
|
||||||
|
|
||||||
|
|
||||||
|
Pattern operators
|
||||||
|
=================
|
||||||
|
|
||||||
|
The operators ``*``, ``**``, ``|``, ``~`` have a special meaning in patterns
|
||||||
|
if they are written in infix notation.
|
||||||
|
|
||||||
|
|
||||||
|
The ``|`` operator
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The ``|`` operator if used as infix operator creates an ordered choice:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template t{0|1}(): expr = 3
|
||||||
|
let a = 1
|
||||||
|
# outputs 3:
|
||||||
|
echo a
|
||||||
|
|
||||||
|
The matching is performed after the compiler performed some optimizations like
|
||||||
|
constant folding, so the following does not work:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template t{0|1}(): expr = 3
|
||||||
|
# outputs 1:
|
||||||
|
echo 1
|
||||||
|
|
||||||
|
The reason is that the compiler already transformed the 1 into "1" for
|
||||||
|
the ``echo`` statement. However, a term rewriting macro should not change the
|
||||||
|
semantics anyway. In fact they can be deactived with the ``--patterns:off``
|
||||||
|
command line option or temporarily with the ``patterns`` pragma.
|
||||||
|
|
||||||
|
|
||||||
|
The ``{}`` operator
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
A pattern expression can be bound to a pattern parameter via the ``expr{param}``
|
||||||
|
notation:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template t{(0|1|2){x}}(x: expr): expr = x+1
|
||||||
|
let a = 1
|
||||||
|
# outputs 2:
|
||||||
|
echo a
|
||||||
|
|
||||||
|
|
||||||
|
The ``~`` operator
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The ``~`` operator is the **not** operator in patterns:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template t{x = (~x){y} and (~x){z}}(x, y, z: bool): stmt =
|
||||||
|
x = y
|
||||||
|
if x: x = z
|
||||||
|
|
||||||
|
var
|
||||||
|
a = false
|
||||||
|
b = true
|
||||||
|
c = false
|
||||||
|
a = b and c
|
||||||
|
echo a
|
||||||
|
|
||||||
|
|
||||||
|
The ``*`` operator
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The ``*`` operator can *flatten* a nested binary expression like ``a & b & c``
|
||||||
|
to ``&(a, b, c)``:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
var
|
||||||
|
calls = 0
|
||||||
|
|
||||||
|
proc `&&`(s: varargs[string]): string =
|
||||||
|
result = s[0]
|
||||||
|
for i in 1..len(s)-1: result.add s[i]
|
||||||
|
inc calls
|
||||||
|
|
||||||
|
template optConc{ `&&` * a }(a: string): expr = &&a
|
||||||
|
|
||||||
|
let space = " "
|
||||||
|
echo "my" && (space & "awe" && "some " ) && "concat"
|
||||||
|
|
||||||
|
# check that it's been optimized properly:
|
||||||
|
doAssert calls == 1
|
||||||
|
|
||||||
|
|
||||||
|
The second operator of `*` must be a parameter; it is used to gather all the
|
||||||
|
arguments. The expression ``"my" && (space & "awe" && "some " ) && "concat"``
|
||||||
|
is passed to ``optConc`` in ``a`` as a special list (of kind ``nkArgList``)
|
||||||
|
which is flattened into a call expression; thus the invocation of ``optConc``
|
||||||
|
produces:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
`&&`("my", space & "awe", "some ", "concat")
|
||||||
|
|
||||||
|
|
||||||
|
The ``**`` operator
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The ``**`` is much like the ``*`` operator, except that it gathers not only
|
||||||
|
all the arguments, but also the matched operators in reverse polish notation:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
import macros
|
||||||
|
|
||||||
|
type
|
||||||
|
TMatrix = object
|
||||||
|
dummy: int
|
||||||
|
|
||||||
|
proc `*`(a, b: TMatrix): TMatrix = nil
|
||||||
|
proc `+`(a, b: TMat): TMatrix = nil
|
||||||
|
proc `-`(a, b: TMatrix): TMatrix = nil
|
||||||
|
proc `$`(a: TMatrix): string = result = $a.dummy
|
||||||
|
proc mat21(): TMatrix =
|
||||||
|
result.dummy = 21
|
||||||
|
|
||||||
|
macro optM{ (`+`|`-`|`*`) ** a }(a: TMatrix): expr =
|
||||||
|
echo treeRepr(a)
|
||||||
|
result = newCall(bindSym"mat21")
|
||||||
|
|
||||||
|
var x, y, z: TMatrix
|
||||||
|
|
||||||
|
echo x + y * z - x
|
||||||
|
|
||||||
|
This transforms passes expression ``x + y * z - x`` to the ``optM`` macro as
|
||||||
|
an ``nnkArgList`` node containing::
|
||||||
|
|
||||||
|
Arglist
|
||||||
|
Sym "x"
|
||||||
|
Sym "y"
|
||||||
|
Sym "z"
|
||||||
|
Sym "*"
|
||||||
|
Sym "+"
|
||||||
|
Sym "x"
|
||||||
|
Sym "-"
|
||||||
|
|
||||||
|
(Which is the reverse polish notation of ``x + y * z - x``.)
|
||||||
|
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
==========
|
||||||
|
|
||||||
|
Parameters in a pattern are type checked in the matching process. If a
|
||||||
|
parameter is of the type ``varargs`` it is treated specially and it can match
|
||||||
|
0 or more arguments in the AST to be matched against:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
template optWrite{
|
||||||
|
write(f, x)
|
||||||
|
((write|writeln){w})(f, y)
|
||||||
|
}(x, y: varargs[expr], f: TFile, w: expr) =
|
||||||
|
w(f, x, y)
|
||||||
|
|
||||||
12
doc/tut2.txt
12
doc/tut2.txt
|
|
@ -286,7 +286,7 @@ Procedures always use static dispatch. For dynamic dispatch replace the
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
type
|
type
|
||||||
TExpr = object ## abstract base class for an expression
|
TExpr = object of TObject ## abstract base class for an expression
|
||||||
TLiteral = object of TExpr
|
TLiteral = object of TExpr
|
||||||
x: int
|
x: int
|
||||||
TPlusExpr = object of TExpr
|
TPlusExpr = object of TExpr
|
||||||
|
|
@ -323,7 +323,7 @@ dispatching:
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
||||||
type
|
type
|
||||||
TThing = object
|
TThing = object of TObject
|
||||||
TUnit = object of TThing
|
TUnit = object of TThing
|
||||||
x: int
|
x: int
|
||||||
|
|
||||||
|
|
@ -702,3 +702,11 @@ regular expressions:
|
||||||
return tkOperator
|
return tkOperator
|
||||||
else:
|
else:
|
||||||
return tkUnknown
|
return tkUnknown
|
||||||
|
|
||||||
|
|
||||||
|
Term rewriting macros
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Term rewriting macros can be used to enhance the compilation process
|
||||||
|
with user defined optimizations; see this `document <trmacros.html>`_ for
|
||||||
|
further information.
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,12 @@ proc `*`(a, b: TMat): TMat = nil
|
||||||
proc `+`(a, b: TMat): TMat = nil
|
proc `+`(a, b: TMat): TMat = nil
|
||||||
proc `-`(a, b: TMat): TMat = nil
|
proc `-`(a, b: TMat): TMat = nil
|
||||||
proc `$`(a: TMat): string = result = $a.dummy
|
proc `$`(a: TMat): string = result = $a.dummy
|
||||||
proc mat32(): TMat =
|
proc mat21(): TMat =
|
||||||
result.dummy = 21
|
result.dummy = 21
|
||||||
|
|
||||||
macro optOps{ (`+`|`-`|`*`) *| a }(a: TMat): expr =
|
macro optOps{ (`+`|`-`|`*`) ** a }(a: TMat): expr =
|
||||||
result = newCall(bindSym"mat32")
|
echo treeRepr(a)
|
||||||
|
result = newCall(bindSym"mat21")
|
||||||
|
|
||||||
#macro optPlus{ `+` * a }(a: varargs[TMat]): expr =
|
#macro optPlus{ `+` * a }(a: varargs[TMat]): expr =
|
||||||
# result = newIntLitNode(21)
|
# result = newIntLitNode(21)
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,14 @@ template testOr{ (arithOps{f})(a, b) }(a, b, f: expr): expr = f(a+1, b)
|
||||||
|
|
||||||
let xx = 10
|
let xx = 10
|
||||||
echo 10*xx
|
echo 10*xx
|
||||||
|
|
||||||
|
template t{x = (~x){y} and (~x){z}}(x, y, z: bool): stmt =
|
||||||
|
x = y
|
||||||
|
if x: x = z
|
||||||
|
|
||||||
|
var
|
||||||
|
a = true
|
||||||
|
b = true
|
||||||
|
c = false
|
||||||
|
a = b and a
|
||||||
|
echo a
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ proc `&&`(s: varargs[string]): string =
|
||||||
for i in 1..len(s)-1: result.add s[i]
|
for i in 1..len(s)-1: result.add s[i]
|
||||||
inc calls
|
inc calls
|
||||||
|
|
||||||
template optConc{ `&&` * a }(a: varargs[string]): expr = &&a
|
template optConc{ `&&` * a }(a: string): expr = &&a
|
||||||
|
|
||||||
let space = " "
|
let space = " "
|
||||||
echo "my" && (space & "awe" && "some " ) && "concat"
|
echo "my" && (space & "awe" && "some " ) && "concat"
|
||||||
|
|
|
||||||
2
todo.txt
2
todo.txt
|
|
@ -2,7 +2,7 @@ version 0.9.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- make 'm: stmt' use overloading resolution
|
- make 'm: stmt' use overloading resolution
|
||||||
- document pattern matching
|
- fix the 'nil' bug in the AST
|
||||||
|
|
||||||
- make 'bind' default for templates and introduce 'mixin'
|
- make 'bind' default for templates and introduce 'mixin'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,22 +97,19 @@ Nimrod plays nice with others
|
||||||
libcurl, mySQL and SQLite are included in the standard distribution.
|
libcurl, mySQL and SQLite are included in the standard distribution.
|
||||||
* A C to Nimrod conversion utility: New bindings to C libraries are easily
|
* A C to Nimrod conversion utility: New bindings to C libraries are easily
|
||||||
generated by ``c2nim``.
|
generated by ``c2nim``.
|
||||||
* A Pascal to Nimrod conversion utility: A large subset of Object Pascal
|
|
||||||
can be translated to Nimrod automatically!
|
|
||||||
|
|
||||||
|
|
||||||
Roadmap to 1.0
|
Roadmap to 1.0
|
||||||
==============
|
==============
|
||||||
|
|
||||||
Version 0.9.0
|
|
||||||
* closures
|
|
||||||
|
|
||||||
Version 0.9.x
|
Version 0.9.x
|
||||||
* recursive iterators/coroutines
|
* first class iterators
|
||||||
* 2-phase type system for better interaction between macros, templates
|
* 2-phase type system for better interaction between macros, templates
|
||||||
and overloading
|
and overloading
|
||||||
* term rewriting macros
|
|
||||||
* the syntactic distinction between statements and expressions will be
|
* the syntactic distinction between statements and expressions will be
|
||||||
removed
|
removed
|
||||||
|
* the binding rules for generics and templates will change
|
||||||
|
* exception tracking
|
||||||
|
* the effect system will be extended
|
||||||
* the need for forward declarations may be removed
|
* the need for forward declarations may be removed
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,8 @@ Language Additions
|
||||||
in templates.
|
in templates.
|
||||||
- Comments can be continued with a backslash continuation character so that
|
- Comments can be continued with a backslash continuation character so that
|
||||||
comment pieces don't have to align on the same column.
|
comment pieces don't have to align on the same column.
|
||||||
|
- Enums can be annotated with ``pure`` so that their field names do not pollute
|
||||||
|
the current scope.
|
||||||
|
|
||||||
|
|
||||||
2012-02-09 Version 0.8.14 released
|
2012-02-09 Version 0.8.14 released
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ FAQ: question
|
||||||
file: ticker
|
file: ticker
|
||||||
|
|
||||||
[Documentation]
|
[Documentation]
|
||||||
doc: "endb;intern;apis;lib;manual;tut1;tut2;nimrodc;overview;filters"
|
doc: "endb;intern;apis;lib;manual;tut1;tut2;nimrodc;overview;filters;trmacros"
|
||||||
doc: "tools;c2nim;niminst;nimgrep"
|
doc: "tools;c2nim;niminst;nimgrep"
|
||||||
pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst;gc"
|
pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst;gc"
|
||||||
srcdoc: "core/macros;pure/marshal;core/typeinfo;core/unsigned"
|
srcdoc: "core/macros;pure/marshal;core/typeinfo;core/unsigned"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue