added tools and web dirs

This commit is contained in:
Andreas Rumpf 2009-09-15 23:22:22 +02:00
commit 66a7e3d37c
489 changed files with 4593 additions and 9878 deletions

363
doc/manual.txt Normal file → Executable file
View file

@ -8,6 +8,10 @@ Nimrod Manual
.. contents::
"Complexity" seems to be a lot like "energy": you can transfer it from the end
user to one/some of the other players, but the total amount seems to remain
pretty much constant for a given task. -- Ran
About this document
===================
@ -171,10 +175,10 @@ preferred. Another advantage is that it frees the programmer from remembering
the exact spelling of an identifier.
Literal strings
String literals
---------------
`Literal strings`:idx: can be delimited by matching double quotes, and can
`String literals`:idx: can be delimited by matching double quotes, and can
contain the following `escape sequences`:idx:\ :
================== ===================================================
@ -202,12 +206,21 @@ contain the following `escape sequences`:idx:\ :
Strings in Nimrod may contain any 8-bit value, except embedded zeros.
Literal strings can also be delimited by three double squotes
Triple quoted string literals
-----------------------------
String literals can also be delimited by three double quotes
``"""`` ... ``"""``.
Literals in this form may run for several lines, may contain ``"`` and do not
interpret any escape sequences.
For convenience, when the opening ``"""`` is immediately followed by a newline,
the newline is not included in the string.
Raw string literals
-------------------
There are also `raw string literals` that are preceded with the letter ``r``
(or ``R``) and are delimited by matching double quotes (just like ordinary
string literals) and do not interpret the escape sequences. This is especially
@ -218,7 +231,22 @@ convenient for regular expressions or Windows paths:
var f = openFile(r"C:\texts\text.txt") # a raw string, so ``\t`` is no tab
Literal characters
Generalized raw string literals
-------------------------------
The construct ``identifier"string literal"`` (without whitespace between the
identifier and the opening quotation mark) is a
`generalized raw string literal`:idx:. It is a shortcut for the construct
``identifier(r"string literal")``, so it denotes a procedure call with a
raw string literal as its only argument. Generalized raw string literals
are especially convenient for embedding mini languages directly into Nimrod
(for example regular expressions).
The construct ``identifier"""string literal"""`` exists too. It is a shortcut
for ``identifier("""string literal""")``.
Character literals
------------------
Character literals are enclosed in single quotes ``''`` and can contain the
@ -501,7 +529,7 @@ designed for this.
Another reason is that Nimrod 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 the ``unicode`` module.
character. ``TRune`` is declared in the ``unicode`` module.
@ -548,7 +576,7 @@ Subrange types
~~~~~~~~~~~~~~
A `subrange`:idx: type is a range of values from an ordinal type (the base
type). To define a subrange type, one must specify it's limiting values: the
highest and lowest value of the type:
lowest and highest value of the type:
.. code-block:: nimrod
type
@ -764,7 +792,7 @@ basetype can only be an ordinal type. The reason is that sets are implemented
as high performance bit vectors.
Sets can be constructed via the set constructor: ``{}`` is the empty set. The
empty set is type combatible with any special set type. The constructor
empty set is type compatible with any special set type. The constructor
can also be used to include elements (and ranges of elements) in the set:
.. code-block:: nimrod
@ -903,9 +931,8 @@ each other:
`closure`:idx:
indicates that the procedure expects a context, a closure that needs
to be passed to the procedure. The implementation is the
same as ``cdecl``, but with a hidden pointer parameter (the
*closure*). The hidden parameter is always the last one.
to be passed to the procedure. The calling convention ``nimcall`` is
compatible to ``closure``.
`syscall`:idx:
The syscall convention is the same as ``__syscall`` in C. It is used for
@ -915,11 +942,108 @@ each other:
The generated C code will not have any explicit calling convention and thus
use the C compiler's default calling convention. This is needed because
Nimrod's default calling convention for procedures is ``fastcall`` to
improve speed. This is unlikely to be needed by the user.
improve speed.
Most calling conventions exist only for the Windows 32-bit platform.
Distinct type
~~~~~~~~~~~~~
A distinct type is new type derived from a `base type`:idx: that is
incompatible with its base type. In particular, it is an essential property
of a distinct type that it **does not** imply a subtype relation between it
and its base type. Explict type conversions from a distinct type to its
base type and vice versa are allowed.
A distinct type can be used to model different physical `units`:idx: with a
numerical base type, for example. The following example models currencies.
Different currencies should not be mixed in monetary calculations. Distinct
types are a perfect tool to model different currencies:
.. code-block:: nimrod
type
TDollar = distinct int
TEuro = distinct int
var
d: TDollar
e: TEuro
echo d + 12
# Error: cannot add a number with no unit and a ``TDollar``
Unfortunetaly, ``d + 12.TDollar`` is not allowed either,
because ``+`` is defined for ``int`` (among others), not for ``TDollar``. So
a ``+`` for dollars needs to be defined:
.. code-block::
proc `+` (x, y: TDollar): TDollar =
result = TDollar(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: int, y: TDollar): TDollar =
result = TDollar(x * int(y))
proc `div` ...
This quickly gets tedious. The implementations are trivial and the compiler
should not generate all this code only to optimize it away later - after all
``+`` for dollars should produce the same binary code as ``+`` for ints.
The pragma ``borrow`` has been designed to solve this problem; in principle
it generates the above trivial implementations:
.. code-block:: nimrod
proc `*` (x: TDollar, y: int): TDollar {.borrow.}
proc `*` (x: int, y: TDollar): TDollar {.borrow.}
proc `div` (x: TDollar, y: int): TDollar {.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``
currency. This can be solved with templates_.
.. code-block:: nimrod
template Additive(typ: typeDesc): stmt =
proc `+` *(x, y: typ): typ {.borrow.}
proc `-` *(x, y: typ): typ {.borrow.}
# unary operators:
proc `+` *(x: typ): typ {.borrow.}
proc `-` *(x: typ): typ {.borrow.}
template Multiplicative(typ, base: typeDesc): stmt =
proc `*` *(x: typ, y: base): typ {.borrow.}
proc `*` *(x: base, y: typ): typ {.borrow.}
proc `div` *(x: typ, y: base): typ {.borrow.}
proc `mod` *(x: typ, y: base): typ {.borrow.}
template Comparable(typ: typeDesc): stmt =
proc `<` * (x, y: typ): bool {.borrow.}
proc `<=` * (x, y: typ): bool {.borrow.}
proc `==` * (x, y: typ): bool {.borrow.}
template DefineCurrency(typ, base: expr): stmt =
type
typ* = distinct base
Additive(typ)
Multiplicative(typ, base)
Comparable(typ)
DefineCurrency(TDollar, int)
DefineCurrency(TEuro, int)
Type relations
--------------
@ -956,7 +1080,7 @@ algorithm determines type equality:
for i in 0..a.tupleLen-1:
if not typeEqualsAux(a[i], b[i], s): return false
result = true
of object, enum, abstract:
of object, enum, distinct:
result = a == b
of proc:
result = typeEqualsAux(a.parameterTuple, b.parameterTuple, s) and
@ -973,7 +1097,7 @@ auxiliary set ``s`` to detect this case.
Subtype relation
~~~~~~~~~~~~~~~~
If object ``b`` inherits from ``a``, ``b`` is a subtype of ``a``. This subtype
If object ``a`` inherits from ``b``, ``a`` is a subtype of ``b``. This subtype
relation is extended to the types ``var``, ``ref``, ``ptr``:
.. code-block:: nimrod
@ -987,27 +1111,70 @@ relation is extended to the types ``var``, ``ref``, ``ptr``:
of var, ref, ptr:
result = isSubtype(a.baseType, b.baseType)
XXX nil is a special value!
.. XXX nil is a special value!
Convertible relation
~~~~~~~~~~~~~~~~~~~~
A type ``a`` is convertible to type ``b`` iff the following algorithm returns
true:
A type ``a`` is **implicitely** convertible to type ``b`` iff the following
algorithm returns true:
.. code-block:: nimrod
proc isConvertible(a, b: PType): bool =
if a.kind == b.kind:
case a.kind
of proc:
# XXX range types?
proc isImplicitelyConvertible(a, b: PType): bool =
case a.kind
of proc:
if b.kind == proc:
var x = a.parameterTuple
var y = b.parameterTuple
if x.tupleLen == y.tupleLen:
for i in 0.. x.tupleLen-1:
if not isSubtype(x[i], y[i]): return false
result = isSubType(b.resultType, a.resultType)
of int8: result = b.kind in {int16, int32, int64, int}
of int16: result = b.kind in {int32, int64, int}
of int32: result = b.kind in {int64, int}
of float: result = b.kind in {float32, float64}
of float32: result = b.kind in {float64, float}
of float64: result = b.kind in {float32, float}
of seq:
result = b.kind == openArray and typeEquals(a.baseType, b.baseType)
of array:
result = b.kind == openArray and typeEquals(a.baseType, b.baseType)
if a.baseType == char and a.indexType.rangeA == 0:
result = b.kind = cstring
of cstring, ptr:
result = b.kind == pointer
of string:
result = b.kind == cstring
A type ``a`` is **explicitely** convertible to type ``b`` iff the following
algorithm returns true:
.. code-block:: nimrod
proc isIntegralType(t: PType): bool =
result = isOrdinal(t) or t.kind in {float, float32, float64}
proc isExplicitelyConvertible(a, b: PType): bool =
if isImplicitelyConvertible(a, b): return true
if isIntegralType(a) and isIntegralType(b): return true
if isSubtype(a, b) or isSubtype(b, a): return true
if a.kind == distinct and typeEquals(a.baseType, b): return true
if b.kind == distinct and typeEquals(b.baseType, a): return true
return false
Assignment compability
~~~~~~~~~~~~~~~~~~~~~~
An expression ``b`` can be assigned to an expression ``a`` iff ``a`` is an
`l-value` and ``isImplicitelyConvertible(b.typ, a.typ)`` holds.
Overloading resolution
~~~~~~~~~~~~~~~~~~~~~~
To be written.
Statements and expressions
@ -1095,7 +1262,7 @@ Type default value
============================ ==============================================
any integer type 0
any float 0.0
char '\0'
char '\\0'
bool false
ref or pointer type nil
procedural type nil
@ -1192,8 +1359,8 @@ a static error is given. This holds only for expressions of ordinal types.
If the expression is not of an ordinal type, and no ``else`` part is
given, control just passes after the ``case`` statement.
To suppress the static error in the ordinal case the programmer needs
to write an ``else`` part with a ``nil`` statement.
To suppress the static error in the ordinal case an ``else`` part with a ``nil``
statement can be used.
When statement
@ -1271,7 +1438,7 @@ Example:
# and tries to add them
var
f: TFile
if openFile(f, "numbers.txt"):
if open(f, "numbers.txt"):
try:
var a = readLine(f)
var b = readLine(f)
@ -1285,7 +1452,7 @@ Example:
except:
echo("Unknown exception!")
finally:
closeFile(f)
close(f)
The statements after the `try`:idx: are executed in sequential order unless
an exception ``e`` is raised. If the exception type of ``e`` matches any
@ -1417,7 +1584,7 @@ Example:
The `while`:idx: statement is executed until the ``expr`` evaluates to false.
Endless loops are no error. ``while`` statements open an `implicit block`,
so that they can be leaved with a ``break`` statement.
so that they can be left with a ``break`` statement.
Continue statement
@ -1562,8 +1729,9 @@ type `var`).
return intToStr(x)
Operators with one parameter are prefix operators, operators with two
parameters are infix operators. There is no way to declare postfix
operators: All postfix operators are built-in and handled by the
parameters are infix operators. (However, the parser distinguishes these from
the operators position within an expression.) There is no way to declare
postfix operators: All postfix operators are built-in and handled by the
grammar explicitely.
Any operator can be called like an ordinary proc with the '`opr`'
@ -1622,18 +1790,13 @@ return values. This can be done in a cleaner way by returning a tuple:
assert t.res == 1
assert t.remainder = 3
Even more elegant is to use `tuple unpacking` to access the tuple's fields:
Even more elegant is to use `tuple unpacking`:idx: to access the tuple's fields:
.. code-block:: nimrod
var (x, y) = divmod(8, 5) # tuple unpacking
assert x == 1
assert y == 3
Unfortunately, this form of tuple unpacking is not yet implemented.
..
XXX remove this as soon as tuple unpacking is implemented
Iterators and the for statement
@ -1655,7 +1818,7 @@ Syntax::
The `for`:idx: statement is an abstract mechanism to iterate over the elements
of a container. It relies on an `iterator`:idx: to do so. Like ``while``
statements, ``for`` statements open an `implicit block`:idx:, so that they
can be leaved with a ``break`` statement. The ``for`` loop declares
can be left with a ``break`` statement. The ``for`` loop declares
iteration variables (``x`` in the example) - their scope reaches until the
end of the loop body. The iteration variables' types are inferred by the
return type of the iterator.
@ -1737,8 +1900,6 @@ possible within a single ``type`` section.
Generics
~~~~~~~~
`Version 0.7.10: Generic types like in the example do not work.`:red:
Example:
.. code-block:: nimrod
@ -1778,11 +1939,9 @@ Example:
# inorder traversal of a binary tree
# recursive iterators are not yet implemented, so this does not work in
# the current compiler!
if root.le != nil:
yield inorder(root.le)
if root.le != nil: yield inorder(root.le)
yield root.data
if root.ri != nil:
yield inorder(root.ri)
if root.ri != nil: yield inorder(root.ri)
var
root: PBinaryTree[string] # instantiate a PBinaryTree with the type string
@ -1799,12 +1958,11 @@ introduce type parameters or to instantiate a generic proc, iterator or type.
Templates
~~~~~~~~~
A `template`:idx: is a simple form of a macro. It operates on parse trees and is
processed in the semantic pass of the compiler. So they integrate well with the
rest of the language and share none of C's preprocessor macros flaws. However,
they may lead to code that is harder to understand and maintain. So one ought
to use them sparingly. The usage of ordinary procs, iterators or generics is
preferred to the usage of templates.
A `template`:idx: is a simple form of a macro: It is a simple substitution
mechanism that operates on Nimrod's abstract syntax trees. It is processed in
the semantic pass of the compiler.
The syntax to *invoke* a template is the same as calling a procedure.
Example:
@ -1815,20 +1973,86 @@ Example:
assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6))
The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact
templates:
| ``a > b`` is transformed into ``b < a``.
| ``a in b`` is transformed into ``contains(b, a)``.
| ``notin`` and ``isnot`` have the obvious meanings.
The "types" of templates can be the symbols ``expr`` (stands for *expression*),
``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type
description*). These are no real types, they just help the compiler parsing.
Real types can be used too; this implies that expressions are expected.
However, for parameter type checking the arguments are semantically checked
before being passed to the template. Other arguments are not semantically
checked before being passed to the template.
The template body does not open a new scope. To open a new scope a ``block``
statement can be used:
.. code-block:: nimrod
template declareInScope(x: expr, t: typeDesc): stmt =
var x: t
template declareInNewScope(x: expr, t: typeDesc): stmt =
# open a new scope:
block:
var x: t
declareInScope(a, int)
a = 42 # works, `a` is known here
declareInNewScope(b, int)
b = 42 # does not work, `b` is unknown
If there is a ``stmt`` parameter it should be the last in the template
declaration, because statements are passed to a template via a
special ``:`` syntax:
.. code-block:: nimrod
template withFile(f, fn, mode: expr, actions: stmt): stmt =
block:
var f: TFile
if open(f, fn, mode):
try:
actions
finally:
close(f)
else:
quit("cannot open: " & fn)
withFile(txt, "ttempl3.txt", fmWrite):
txt.writeln("line 1")
txt.writeln("line 2")
In the example the two ``writeln`` statements are bound to the ``actions``
parameter.
**Style note**: For code readability, it is the best idea to use the least
powerful programming construct that still suffices. So the "check list" is:
(1) Use an ordinary proc/iterator, if possible.
(2) Else: Use a generic proc/iterator, if possible.
(3) Else: Use a template, if possible.
(4) Else: Use a macro.
Macros
------
`Macros`:idx: are the most powerful feature of Nimrod. They can be used
to implement `domain specific languages`:idx:. But they may lead to code
that is harder to understand and maintain. So one ought to use them sparingly.
to implement `domain specific languages`:idx:.
While macros enable advanced compile-time code tranformations, they
cannot change Nimrod's syntax. However, this is no real restriction because
Nimrod's syntax is flexible enough anyway.
To write macros, one needs to know how the Nimrod concrete syntax is converted
to an abstract syntax tree. (Unfortunately the AST is not yet documented.)
to an abstract syntax tree.
There are two ways to invoke a macro:
(1) invoking a macro like a procedure call (`expression macros`)
@ -1847,7 +2071,7 @@ variable number of arguments:
import macros
macro debug(n: expr): stmt =
# `n` is a Nimrod AST that contains the whole macro expression
# `n` is a Nimrod AST that contains the whole macro invokation
# this macro returns a list of statements:
result = newNimNode(nnkStmtList, n)
# iterate over any argument that is passed to this macro:
@ -1948,6 +2172,7 @@ This is best illustrated by an example:
main()
.. code-block:: nimrod
# Module B
import A # A is not parsed here! Only the already known symbols
# of A are imported.
@ -1981,7 +2206,7 @@ Tuple or object scope
The field identifiers inside a tuple or object definition are valid in the
following places:
* To the end of the tuple/object definition
* To the end of the tuple/object definition.
* Field designators of a variable of the given tuple/object type.
* In all descendent types of the object type.
@ -2000,9 +2225,11 @@ iterator in which case the overloading resolution takes place:
# Module A
var x*: string
.. code-block:: nimrod
# Module B
var x*: int
.. code-block:: nimrod
# Module C
import A, B
write(stdout, x) # error: x is ambiguous
@ -2035,26 +2262,22 @@ processed on the fly during semantic checking. Pragmas are enclosed in the
special ``{.`` and ``.}`` curly brackets.
define pragma
-------------
The `define`:idx: pragma defines a conditional symbol. This symbol may only be
used in other pragmas and in the ``defined`` expression and not in ordinary
Nimrod source code. The conditional symbols go into a special symbol table.
The compiler defines the target processor and the target operating
system as conditional symbols.
Warning: The ``define`` pragma is deprecated as it conflicts with separate
compilation! One should use boolean constants as a replacement - this is
cleaner anyway.
noSideEffect pragma
-------------------
The `noSideEffect`:idx: pragma is used to mark a proc/iterator to have no side
effects. This means that the proc/iterator only changes locations that are
reachable from its parameters and the return value only depends on the
arguments. If none of its parameters have the type ``var T``
or ``ref T`` or ``ptr T`` this means no locations are modified. It is a static
error to mark a proc/iterator to have no side effect if the compiler cannot
verify this.
undef pragma
------------
The `undef`:idx: pragma the counterpart to the define pragma. It undefines a
conditional symbol.
Warning: The ``undef`` pragma is deprecated as it conflicts with separate
compilation!
compileTime pragma
------------------
The `compileTime`:idx: pragma is used to mark a proc to be used at compile
time only. No code will be generated for it. Compile time procs are useful
as helpers for macros.
error pragma