fixed typos in documentation

This commit is contained in:
Andreas Rumpf 2009-11-15 17:46:15 +01:00
commit 281609c358
6 changed files with 316 additions and 248 deletions

View file

@ -24,8 +24,8 @@ ast type definitions of the abstract syntax tree (AST) and
node constructors node constructors
astalgo algorithms for containers of AST nodes; converting the astalgo algorithms for containers of AST nodes; converting the
AST to YAML; the symbol table AST to YAML; the symbol table
passes implement the passes managemer for passes over the AST passes implement the passes manager for passes over the AST
trees few algorithms for nodes; this module is less important trees some algorithms for nodes; this module is less important
types module for traversing type graphs; also contain several types module for traversing type graphs; also contain several
helpers for dealing with types helpers for dealing with types

View file

@ -102,7 +102,7 @@ The terminals ``IND`` (indentation), ``DED`` (dedentation) and ``SAD``
These terminals are only generated for lines that are not empty. These terminals are only generated for lines that are not empty.
The parser and the scanner communicate over a stack which indentation terminal The parser and the scanner communicate over a stack which indentation terminal
should be generated: The stack consists of integers counting the spaces. The should be generated: the stack consists of integers counting the spaces. The
stack is initialized with a zero on its top. The scanner reads from the stack: stack is initialized with a zero on its top. The scanner reads from the stack:
If the current indentation token consists of more spaces than the entry at the If the current indentation token consists of more spaces than the entry at the
top of the stack, a ``IND`` token is generated, else if it consists of the same top of the stack, a ``IND`` token is generated, else if it consists of the same
@ -168,7 +168,7 @@ language.
Nimrod is a `style-insensitive`:idx: language. This means that it is not Nimrod is a `style-insensitive`:idx: language. This means that it is not
case-sensitive and even underscores are ignored: case-sensitive and even underscores are ignored:
**type** is a reserved word, and so is **TYPE** or **T_Y_P_E**. The idea behind **type** is a reserved word, and so is **TYPE** or **T_Y_P_E**. The idea behind
this is that this allows programmers to use their own prefered spelling style this is that this allows programmers to use their own preferred spelling style
and libraries written by different programmers cannot use incompatible and libraries written by different programmers cannot use incompatible
conventions. A Nimrod-aware editor or IDE can show the identifiers as conventions. A Nimrod-aware editor or IDE can show the identifiers as
preferred. Another advantage is that it frees the programmer from remembering preferred. Another advantage is that it frees the programmer from remembering
@ -253,7 +253,7 @@ Character literals are enclosed in single quotes ``''`` and can contain the
same escape sequences as strings - with one exception: ``\n`` is not allowed same escape sequences as strings - with one exception: ``\n`` is not allowed
as it may be wider than one character (often it is the pair CR/LF for example). as it may be wider than one character (often it is the pair CR/LF for example).
A character is not an Unicode character but a single byte. The reason for this 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 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 programs will still handle UTF-8 properly as UTF-8 was specially designed for
this. this.
Another reason is that Nimrod can thus support ``array[char, int]`` or Another reason is that Nimrod can thus support ``array[char, int]`` or
@ -284,13 +284,13 @@ Numerical constants
FLOAT64_LIT ::= ( FLOAT_LIT | INT_LIT ) '\'' ('f' | 'F') '64' FLOAT64_LIT ::= ( FLOAT_LIT | INT_LIT ) '\'' ('f' | 'F') '64'
As can be seen in the productions, numerical constants can contain unterscores As can be seen in the productions, numerical constants can contain underscores
for readability. Integer and floating point literals may be given in decimal (no for readability. Integer and floating point literals may be given in decimal (no
prefix), binary (prefix ``0b``), octal (prefix ``0o``) and hexadecimal prefix), binary (prefix ``0b``), octal (prefix ``0o``) and hexadecimal
(prefix ``0x``) notation. (prefix ``0x``) notation.
There exists a literal for each numerical type that is There exists a literal for each numerical type that is
defined. The suffix starting with an apostophe ('\'') is called a defined. The suffix starting with an apostrophe ('\'') is called a
`type suffix`:idx:. Literals without a type prefix are of the type ``int``, `type suffix`:idx:. Literals without a type prefix are of the type ``int``,
unless the literal contains a dot or an ``E`` in which case it is of unless the literal contains a dot or an ``E`` in which case it is of
type ``float``. type ``float``.
@ -429,7 +429,7 @@ Pre-defined numerical types
These integer types are pre-defined: These integer types are pre-defined:
``int`` ``int``
the generic signed integer type; its size is platform dependant the generic signed integer type; its size is platform dependent
(the compiler chooses the processor's fastest integer type) (the compiler chooses the processor's fastest integer type)
this type should be used in general. An integer literal that has no type this type should be used in general. An integer literal that has no type
suffix is of this type. suffix is of this type.
@ -450,7 +450,7 @@ they cannot lead to over- or underflow errors. Unsigned operations use the
operation meaning operation meaning
====================== ====================================================== ====================== ======================================================
``a +% b`` unsigned integer addition ``a +% b`` unsigned integer addition
``a -% b`` unsigned integer substraction ``a -% b`` unsigned integer subtraction
``a *% b`` unsigned integer multiplication ``a *% b`` unsigned integer multiplication
``a /% b`` unsigned integer division ``a /% b`` unsigned integer division
``a %% b`` unsigned integer modulo operation ``a %% b`` unsigned integer modulo operation
@ -472,7 +472,7 @@ operation meaning
The following floating point types are pre-defined: The following floating point types are pre-defined:
``float`` ``float``
the generic floating point type; its size is platform dependant the generic floating point type; its size is platform dependent
(the compiler chooses the processor's fastest floating point type) (the compiler chooses the processor's fastest floating point type)
this type should be used in general this type should be used in general
@ -488,7 +488,7 @@ loses information, the `EOutOfRange`:idx: exception is raised (if the error
cannot be detected at compile time). cannot be detected at compile time).
Automatic type conversion in expressions with different kinds Automatic type conversion in expressions with different kinds
of floating point types is performed: The smaller type is of floating point types is performed: the smaller type is
converted to the larger. Arithmetic performed on floating point types converted to the larger. Arithmetic performed on floating point types
follows the IEEE standard. Integer types are not converted to floating point follows the IEEE standard. Integer types are not converted to floating point
types automatically and vice versa. types automatically and vice versa.
@ -522,7 +522,7 @@ Character type
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
The `character type`:idx: is named ``char`` in Nimrod. Its size is one byte. The `character type`:idx: is named ``char`` in Nimrod. Its size is one byte.
Thus it cannot represent an UTF-8 character, but a part of it. Thus it cannot represent an UTF-8 character, but a part of it.
The reason for this is efficiency: For the overwhelming majority of use-cases, 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 the resulting programs will still handle UTF-8 properly as UTF-8 was specially
designed for this. designed for this.
Another reason is that Nimrod can support ``array[char, int]`` or Another reason is that Nimrod can support ``array[char, int]`` or
@ -559,12 +559,12 @@ types can be assigned an explicit ordinal value. However, the ordinal values
have to be in ascending order. A field whose ordinal value is not have to be in ascending order. A field whose ordinal value is not
explicitly given is assigned the value of the previous field + 1. explicitly given is assigned the value of the previous field + 1.
An explicit ordered enum can have *wholes*: An explicit ordered enum can have *holes*:
.. code-block:: nimrod .. code-block:: nimrod
type type
TTokenType = enum TTokenType = enum
a = 2, b = 4, c = 89 # wholes are valid a = 2, b = 4, c = 89 # holes are valid
However, it is then not an ordinal anymore, so it is not possible to use these However, it is then not an ordinal anymore, so it is not possible to use these
enums as an index type for arrays. The procedures ``inc``, ``dec``, ``succ`` enums as an index type for arrays. The procedures ``inc``, ``dec``, ``succ``
@ -598,6 +598,7 @@ similar to a sequence of characters. However, strings in Nimrod are both
zero-terminated and have a length field. One can retrieve the length with the zero-terminated and have a length field. One can retrieve the length with the
builtin ``len`` procedure; the length never counts the terminating zero. builtin ``len`` procedure; the length never counts the terminating zero.
The assignment operator for strings always copies the string. The assignment operator for strings always copies the string.
The ``&`` operator concatenates strings.
Strings are compared by their lexicographical order. All comparison operators Strings are compared by their lexicographical order. All comparison operators
are available. Strings can be indexed like arrays (lower bound is 0). Unlike are available. Strings can be indexed like arrays (lower bound is 0). Unlike
@ -614,18 +615,18 @@ Per convention, all strings are UTF-8 strings, but this is not enforced. For
example, when reading strings from binary files, they are merely a sequence of example, when reading strings from binary files, they are merely a sequence of
bytes. The index operation ``s[i]`` means the i-th *char* of ``s``, not the bytes. The index operation ``s[i]`` means the i-th *char* of ``s``, not the
i-th *unichar*. The iterator ``runes`` from the ``unicode`` i-th *unichar*. The iterator ``runes`` from the ``unicode``
module can be used for iteration over all unicode characters. module can be used for iteration over all Unicode characters.
Structured types Structured types
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
A variable of a `structured type`:idx: can hold multiple values at the same A variable of a `structured type`:idx: can hold multiple values at the same
time. Stuctured types can be nested to unlimited levels. Arrays, sequences, time. Structured types can be nested to unlimited levels. Arrays, sequences,
tuples, objects and sets belong to the structured types. tuples, objects and sets belong to the structured types.
Array and sequence types Array and sequence types
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
`Arrays`:idx: are a homogenous type, meaning that each element in the array `Arrays`:idx: are a homogeneous type, meaning that each element in the array
has the same type. Arrays always have a fixed length which is specified at has the same type. Arrays always have a fixed length which is specified at
compile time (except for open arrays). They can be indexed by any ordinal type. compile time (except for open arrays). They can be indexed by any ordinal type.
A parameter ``A`` may be an *open array*, in which case it is indexed by A parameter ``A`` may be an *open array*, in which case it is indexed by
@ -658,6 +659,8 @@ The lower bound of an array or sequence may be received by the built-in proc
``low()``, the higher bound by ``high()``. The length may be ``low()``, the higher bound by ``high()``. The length may be
received by ``len()``. ``low()`` for a sequence or an open array always returns received by ``len()``. ``low()`` for a sequence or an open array always returns
0, as this is the first valid index. 0, as this is the first valid index.
One can append elements to a sequence with the ``add()`` proc or the ``&`` operator,
and remove (and get) the last element of a sequence with the ``pop()`` proc.
The notation ``x[i]`` can be used to access the i-th element of ``x``. The notation ``x[i]`` can be used to access the i-th element of ``x``.
@ -686,10 +689,10 @@ support nested open arrays.
Tuples and object types Tuples and object types
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
A variable of a `tuple`:idx: or `object`:idx: type is a heterogenous storage A variable of a `tuple`:idx: or `object`:idx: type is a heterogeneous storage
container. container.
A tuple or object defines various named *fields* of a type. A tuple also A tuple or object defines various named *fields* of a type. A tuple also
defines an *order* of the fields. Tuples are meant for heterogenous storage defines an *order* of the fields. Tuples are meant for heterogeneous storage
types with no overhead and few abstraction possibilities. The constructor ``()`` types with no overhead and few abstraction possibilities. The constructor ``()``
can be used to construct tuples. The order of the fields in the constructor can be used to construct tuples. The order of the fields in the constructor
must match the order of the tuple's definition. Different tuple-types are must match the order of the tuple's definition. Different tuple-types are
@ -736,7 +739,7 @@ the ``is`` operator can be used to determine the object's type.
assert(student is TStudent) # is true assert(student is TStudent) # is true
Object fields that should be visible from outside the defining module, have to Object fields that should be visible from outside the defining module, have to
marked by ``*``. In contrast to tuples, different object types are be marked by ``*``. In contrast to tuples, different object types are
never *equivalent*. never *equivalent*.
@ -760,9 +763,9 @@ An example:
nkIf # an if statement nkIf # an if statement
PNode = ref TNode PNode = ref TNode
TNode = object TNode = object
case kind: TNodeKind # the ``kind`` field is the discriminant case kind: TNodeKind # the ``kind`` field is the discriminator
of nkInt: intVal: int of nkInt: intVal: int
of nkFloat: floavVal: float of nkFloat: floatVal: float
of nkString: strVal: string of nkString: strVal: string
of nkAdd, nkSub: of nkAdd, nkSub:
leftOp, rightOp: PNode leftOp, rightOp: PNode
@ -796,7 +799,7 @@ can also be used to include elements (and ranges of elements) in the set:
.. code-block:: nimrod .. code-block:: nimrod
{'a'..'z', '0'..'9'} # This constructs a set that conains the {'a'..'z', '0'..'9'} # This constructs a set that contains the
# letters from 'a' to 'z' and the digits # letters from 'a' to 'z' and the digits
# from '0' to '9' # from '0' to '9'
@ -821,7 +824,7 @@ operation meaning
Reference and pointer types Reference and pointer types
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
References (similiar to `pointers`:idx: in other programming languages) are a References (similar to `pointers`:idx: in other programming languages) are a
way to introduce many-to-one relationships. This means different references can way to introduce many-to-one relationships. This means different references can
point to and modify the same location in memory. point to and modify the same location in memory.
@ -864,7 +867,7 @@ further information.
If a reference points to *nothing*, it has the value ``nil``. If a reference points to *nothing*, it has the value ``nil``.
Special care has to be taken if an untraced object contains traced objects like Special care has to be taken if an untraced object contains traced objects like
traced references, strings or sequences: In order to free everything properly, traced references, strings or sequences: in order to free everything properly,
the built-in procedure ``GCunref`` has to be called before freeing the the built-in procedure ``GCunref`` has to be called before freeing the
untraced memory manually! untraced memory manually!
@ -891,7 +894,7 @@ Example:
forEach(printItem) # this will NOT work because calling conventions differ forEach(printItem) # this will NOT work because calling conventions differ
A subtle issue with procedural types is that the calling convention of the A subtle issue with procedural types is that the calling convention of the
procedure influences the type compability: Procedural types are only compatible procedure influences the type compatibility: procedural types are only compatible
if they have the same calling convention. if they have the same calling convention.
Nimrod supports these `calling conventions`:idx:, which are all incompatible to Nimrod supports these `calling conventions`:idx:, which are all incompatible to
@ -916,7 +919,7 @@ each other:
The inline convention means the the caller should not call the procedure, The inline convention means the the caller should not call the procedure,
but inline its code directly. Note that Nimrod does not inline, but leaves but inline its code directly. Note that Nimrod does not inline, but leaves
this to the C compiler. Thus it generates ``__inline`` procedures. This is this to the C compiler. Thus it generates ``__inline`` procedures. This is
only a hint for the compiler: It may completely ignore it and only a hint for the compiler: it may completely ignore it and
it may inline procedures that are not marked as ``inline``. it may inline procedures that are not marked as ``inline``.
`fastcall`:idx: `fastcall`:idx:
@ -961,7 +964,7 @@ Distinct type
A distinct type is new type derived from a `base type`:idx: that is 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 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 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 and its base type. Explicit type conversions from a distinct type to its
base type and vice versa are allowed. base type and vice versa are allowed.
A distinct type can be used to model different physical `units`:idx: with a A distinct type can be used to model different physical `units`:idx: with a
@ -982,7 +985,7 @@ types are a perfect tool to model different currencies:
echo d + 12 echo d + 12
# Error: cannot add a number with no unit and a ``TDollar`` # Error: cannot add a number with no unit and a ``TDollar``
Unfortunetaly, ``d + 12.TDollar`` is not allowed either, Unfortunately, ``d + 12.TDollar`` is not allowed either,
because ``+`` is defined for ``int`` (among others), not for ``TDollar``. So because ``+`` is defined for ``int`` (among others), not for ``TDollar``. So
a ``+`` for dollars needs to be defined: a ``+`` for dollars needs to be defined:
@ -1124,12 +1127,12 @@ relation is extended to the types ``var``, ``ref``, ``ptr``:
Convertible relation Convertible relation
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
A type ``a`` is **implicitely** convertible to type ``b`` iff the following A type ``a`` is **implicitly** convertible to type ``b`` iff the following
algorithm returns true: algorithm returns true:
.. code-block:: nimrod .. code-block:: nimrod
# XXX range types? # XXX range types?
proc isImplicitelyConvertible(a, b: PType): bool = proc isImplicitlyConvertible(a, b: PType): bool =
case a.kind case a.kind
of proc: of proc:
if b.kind == proc: if b.kind == proc:
@ -1156,15 +1159,15 @@ algorithm returns true:
of string: of string:
result = b.kind == cstring result = b.kind == cstring
A type ``a`` is **explicitely** convertible to type ``b`` iff the following A type ``a`` is **explicitly** convertible to type ``b`` iff the following
algorithm returns true: algorithm returns true:
.. code-block:: nimrod .. code-block:: nimrod
proc isIntegralType(t: PType): bool = proc isIntegralType(t: PType): bool =
result = isOrdinal(t) or t.kind in {float, float32, float64} result = isOrdinal(t) or t.kind in {float, float32, float64}
proc isExplicitelyConvertible(a, b: PType): bool = proc isExplicitlyConvertible(a, b: PType): bool =
if isImplicitelyConvertible(a, b): return true if isImplicitlyConvertible(a, b): return true
if isIntegralType(a) and isIntegralType(b): return true if isIntegralType(a) and isIntegralType(b): return true
if isSubtype(a, b) or isSubtype(b, a): return true if isSubtype(a, b) or isSubtype(b, a): return true
if a.kind == distinct and typeEquals(a.baseType, b): return true if a.kind == distinct and typeEquals(a.baseType, b): return true
@ -1176,7 +1179,7 @@ Assignment compability
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
An expression ``b`` can be assigned to an expression ``a`` iff ``a`` is an An expression ``b`` can be assigned to an expression ``a`` iff ``a`` is an
`l-value` and ``isImplicitelyConvertible(b.typ, a.typ)`` holds. `l-value` and ``isImplicitlyConvertible(b.typ, a.typ)`` holds.
Overloading resolution Overloading resolution
@ -1251,7 +1254,7 @@ Syntax::
`Var`:idx: statements declare new local and global variables and `Var`:idx: statements declare new local and global variables and
initialize them. A comma seperated list of variables can be used to specify initialize them. A comma separated list of variables can be used to specify
variables of the same type: variables of the same type:
.. code-block:: nimrod .. code-block:: nimrod
@ -1260,7 +1263,7 @@ variables of the same type:
a: int = 0 a: int = 0
x, y, z: int x, y, z: int
If an initializer is given the type can be omitted: The variable is of the If an initializer is given the type can be omitted: the variable is of the
same type as the initializing expression. Variables are always initialized same type as the initializing expression. Variables are always initialized
with a default value if there is no initializing expression. The default with a default value if there is no initializing expression. The default
value depends on the type and is always a zero in binary. value depends on the type and is always a zero in binary.
@ -1401,7 +1404,7 @@ exceptions:
semantics! However, each ``expr`` is checked for semantics. semantics! However, each ``expr`` is checked for semantics.
The ``when`` statement enables conditional compilation techniques. As The ``when`` statement enables conditional compilation techniques. As
a special syntatic extension, the ``when`` construct is also available a special syntactic extension, the ``when`` construct is also available
within ``object`` definitions. within ``object`` definitions.
@ -1469,7 +1472,7 @@ The statements following the ``except`` clauses are called
`exception handlers`:idx:. `exception handlers`:idx:.
The empty `except`:idx: clause is executed if there is an exception that is The empty `except`:idx: clause is executed if there is an exception that is
in no list. It is similiar to an ``else`` clause in ``if`` statements. in no list. It is similar to an ``else`` clause in ``if`` statements.
If there is a `finally`:idx: clause, it is always executed after the If there is a `finally`:idx: clause, it is always executed after the
exception handlers. exception handlers.
@ -1508,7 +1511,7 @@ variables, ``result`` is initialized to (binary) zero:
.. code-block:: nimrod .. code-block:: nimrod
proc returnZero(): int = proc returnZero(): int =
# implicitely returns 0 # implicitly returns 0
Yield statement Yield statement
@ -1741,8 +1744,8 @@ type `var`).
Operators with one parameter are prefix operators, operators with two Operators with one parameter are prefix operators, operators with two
parameters are infix operators. (However, the parser distinguishes these from parameters are infix operators. (However, the parser distinguishes these from
the operators position within an expression.) There is no way to declare the operators position within an expression.) There is no way to declare
postfix operators: All postfix operators are built-in and handled by the postfix operators: all postfix operators are built-in and handled by the
grammar explicitely. grammar explicitly.
Any operator can be called like an ordinary proc with the '`opr`' Any operator can be called like an ordinary proc with the '`opr`'
notation. (Thus an operator can have more than two parameters): notation. (Thus an operator can have more than two parameters):
@ -1870,11 +1873,11 @@ dispatching:
collide(a, b) # output: 2 collide(a, b) # output: 2
Invokation of a multi-method cannot be ambiguous: Collide 2 is prefered over Invocation of a multi-method cannot be ambiguous: collide 2 is preferred over
collide 1 because the resolution works from left to right. collide 1 because the resolution works from left to right.
In the example ``TUnit, TThing`` is prefered over ``TThing, TUnit``. In the example ``TUnit, TThing`` is prefered over ``TThing, TUnit``.
**Perfomance note**: Nimrod does not produce a virtual method table, but **Performance note**: Nimrod does not produce a virtual method table, but
generates dispatch trees. This avoids the expensive indirect branch for method generates dispatch trees. This avoids the expensive indirect branch for method
calls and enables inlining. However, other optimizations like compile time calls and enables inlining. However, other optimizations like compile time
evaluation or dead code elimination do not work with methods. evaluation or dead code elimination do not work with methods.
@ -2166,7 +2169,7 @@ Macros
`Macros`:idx: are the most powerful feature of Nimrod. They can be used `Macros`:idx: are the most powerful feature of Nimrod. They can be used
to implement `domain specific languages`:idx:. to implement `domain specific languages`:idx:.
While macros enable advanced compile-time code tranformations, they While macros enable advanced compile-time code transformations, they
cannot change Nimrod's syntax. However, this is no real restriction because cannot change Nimrod's syntax. However, this is no real restriction because
Nimrod's syntax is flexible enough anyway. Nimrod's syntax is flexible enough anyway.
@ -2190,7 +2193,7 @@ variable number of arguments:
import macros import macros
macro debug(n: expr): stmt = macro debug(n: expr): stmt =
# `n` is a Nimrod AST that contains the whole macro invokation # `n` is a Nimrod AST that contains the whole macro invocation
# this macro returns a list of statements: # this macro returns a list of statements:
result = newNimNode(nnkStmtList, n) result = newNimNode(nnkStmtList, n)
# iterate over any argument that is passed to this macro: # iterate over any argument that is passed to this macro:
@ -2239,14 +2242,14 @@ invoked by an expression following a colon::
| 'except' exceptList ':' stmt )* | 'except' exceptList ':' stmt )*
['else' ':' stmt] ['else' ':' stmt]
The following example outlines a macro that generates a lexical analyser from The following example outlines a macro that generates a lexical analyzer from
regular expressions: regular expressions:
.. code-block:: nimrod .. code-block:: nimrod
import macros import macros
macro case_token(n: stmt): stmt = macro case_token(n: stmt): stmt =
# creates a lexical analyser from regular expressions # creates a lexical analyzer from regular expressions
# ... (implementation is an exercise for the reader :-) # ... (implementation is an exercise for the reader :-)
nil nil
@ -2268,7 +2271,7 @@ Nimrod supports splitting a program into pieces by a `module`:idx: concept.
Each module needs to be in its own file. Modules enable Each module needs to be in its own file. Modules enable
`information hiding`:idx: and `separate compilation`:idx:. A module may gain `information hiding`:idx: and `separate compilation`:idx:. A module may gain
access to symbols of another module by the `import`:idx: statement. access to symbols of another module by the `import`:idx: statement.
`Recursive module dependancies`:idx: are allowed, but slightly subtle. Only `Recursive module dependencies`:idx: are allowed, but slightly subtle. Only
top-level symbols that are marked with an asterisk (``*``) are exported. top-level symbols that are marked with an asterisk (``*``) are exported.
The algorithm for compiling modules is: The algorithm for compiling modules is:
@ -2327,7 +2330,7 @@ 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. * Field designators of a variable of the given tuple/object type.
* In all descendent types of the object type. * In all descendant types of the object type.
Module scope Module scope
~~~~~~~~~~~~ ~~~~~~~~~~~~
@ -2336,7 +2339,7 @@ the end of the module. Identifiers from indirectly dependent modules are *not*
available. The `system`:idx: module is automatically imported in every other available. The `system`:idx: module is automatically imported in every other
module. module.
If a module imports an identifier by two different modules, each occurance of If a module imports an identifier by two different modules, each occurrence of
the identifier has to be qualified, unless it is an overloaded procedure or the identifier has to be qualified, unless it is an overloaded procedure or
iterator in which case the overloading resolution takes place: iterator in which case the overloading resolution takes place:
@ -2394,7 +2397,7 @@ verify this.
procvar pragma procvar pragma
-------------- --------------
The `procvar`:idx: pragma is used to mark a proc so that it can be passed to a The `procvar`:idx: pragma is used to mark a proc that it can be passed to a
procedural variable. procedural variable.

View file

@ -178,6 +178,6 @@ There are two ways to construct a PEG in Nimrod code:
`peg` proc. `peg` proc.
(2) Constructing the AST directly with proc calls. This method does not (2) Constructing the AST directly with proc calls. This method does not
support constructing rules, only simple expressions and is not as support constructing rules, only simple expressions and is not as
convenient. It's only advantage is that it does not pull in the whole PEG convenient. Its only advantage is that it does not pull in the whole PEG
parser into your executable. parser into your executable.

View file

@ -21,7 +21,7 @@ or statements.
The first program The first program
================= =================
We start the tour with a modified "hallo world" program: We start the tour with a modified "hello world" program:
.. code-block:: Nimrod .. code-block:: Nimrod
# This is a comment # This is a comment
@ -45,7 +45,7 @@ The most used commands and switches have abbreviations, so you can also use::
nimrod c -r greetings.nim nimrod c -r greetings.nim
Though it should be pretty obvious what the program does, I will explain the Though it should be pretty obvious what the program does, I will explain the
syntax: Statements which are not indented are executed when the program syntax: statements which are not indented are executed when the program
starts. Indentation is Nimrod's way of grouping statements. Indentation is starts. Indentation is Nimrod's way of grouping statements. Indentation is
done with spaces only, tabulators are not allowed. done with spaces only, tabulators are not allowed.
@ -59,9 +59,9 @@ returned by the ``readline`` procedure. Since the compiler knows that
var name = readline(stdin) var name = readline(stdin)
Note that this is basically the only form of type inference that exists in Note that this is basically the only form of type inference that exists in
Nimrod: It is a good compromise between brevity and readability. Nimrod: it is a good compromise between brevity and readability.
The "hallo world" program contains several identifiers that are already The "hello world" program contains several identifiers that are already
known to the compiler: ``echo``, ``readLine``, etc. These built-in items are known to the compiler: ``echo``, ``readLine``, etc. These built-in items are
declared in the system_ module which is implicitly imported by any other declared in the system_ module which is implicitly imported by any other
module. module.
@ -70,12 +70,12 @@ module.
Lexical elements Lexical elements
================ ================
Let us look at Nimrod's lexical elements in more detail: Like other Let us look at Nimrod's lexical elements in more detail: like other
programming languages Nimrod consists of (string) literals, identifiers, programming languages Nimrod consists of (string) literals, identifiers,
keywords, comments, operators, and other punctation marks. Case is keywords, comments, operators, and other punctuation marks. Case is
*insignificant* in Nimrod and even underscores are ignored: *insignificant* in Nimrod and even underscores are ignored:
``This_is_an_identifier`` and this is the same identifier ``This_is_an_identifier`` and ``ThisIsAnIdentifier`` are the same identifier.
``ThisIsAnIdentifier``. This feature enables you to use other This feature enables you to use other
people's code without bothering about a naming convention that conflicts with people's code without bothering about a naming convention that conflicts with
yours. It also frees you from remembering the exact spelling of an identifier yours. It also frees you from remembering the exact spelling of an identifier
(was it ``parseURL`` or ``parseUrl`` or ``parse_URL``?). (was it ``parseURL`` or ``parseUrl`` or ``parse_URL``?).
@ -86,7 +86,7 @@ String and character literals
String literals are enclosed in double quotes; character literals in single String literals are enclosed in double quotes; character literals in single
quotes. Special characters are escaped with ``\``: ``\n`` means newline, ``\t`` quotes. Special characters are escaped with ``\``: ``\n`` means newline, ``\t``
means tabulator, etc. There exist also *raw* string literals: means tabulator, etc. There are also *raw* string literals:
.. code-block:: Nimrod .. code-block:: Nimrod
r"C:\program files\nim" r"C:\program files\nim"
@ -127,7 +127,7 @@ which code snippet the comment refers to. Since comments are a proper part of
the syntax, watch their indentation: the syntax, watch their indentation:
.. code-block:: .. code-block::
Echo("Hallo!") Echo("Hello!")
# comment has the same indentation as above statement -> fine # comment has the same indentation as above statement -> fine
Echo("Hi!") Echo("Hi!")
# comment has not the right indentation -> syntax error! # comment has not the right indentation -> syntax error!
@ -204,7 +204,7 @@ Control flow statements
======================= =======================
The greetings program consists of 3 statements that are executed sequentially. The greetings program consists of 3 statements that are executed sequentially.
Only the most primitive programs can get away with that: Branching and looping Only the most primitive programs can get away with that: branching and looping
are needed too. are needed too.
@ -245,7 +245,7 @@ a multi-branch:
else: else:
Echo("Hi, ", name, "!") Echo("Hi, ", name, "!")
As can be seen, for an ``of`` branch a comma separated list of values is also As it can be seen, for an ``of`` branch a comma separated list of values is also
allowed. allowed.
The case statement can deal with integers, other ordinal types and strings. The case statement can deal with integers, other ordinal types and strings.
@ -262,7 +262,7 @@ For integers or other ordinal types value ranges are also possible:
of 0..2, 4..7: Echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}") of 0..2, 4..7: Echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}")
of 3, 8: Echo("The number is 3 or 8") of 3, 8: Echo("The number is 3 or 8")
However, the above code does not compile: The reason is that you have to cover However, the above code does not compile: the reason is that you have to cover
every value that ``n`` may contain, but the code only handles the values every value that ``n`` may contain, but the code only handles the values
``0..8``. Since it is not very practical to list every other possible integer ``0..8``. Since it is not very practical to list every other possible integer
(though it is possible thanks to the range notation), we fix this by telling (though it is possible thanks to the range notation), we fix this by telling
@ -276,8 +276,8 @@ the compiler that for every other value nothing should be done:
else: nil else: nil
The ``nil`` statement is a *do nothing* statement. The compiler knows that a The ``nil`` statement is a *do nothing* statement. The compiler knows that a
case statement with an else part cannot fail and thus the error disappers. Note case statement with an else part cannot fail and thus the error disappears. Note
that it is impossible to cover any possible string value: That is why there is that it is impossible to cover all possible string values: that is why there is
no such check for string cases. no such check for string cases.
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
@ -306,7 +306,7 @@ he types in nothing (only presses RETURN).
For statement For statement
------------- -------------
The `for`:idx: statement is a construct to loop over any elements an *iterator* The `for`:idx: statement is a construct to loop over any element an *iterator*
provides. The example uses the built-in ``countup`` iterator: provides. The example uses the built-in ``countup`` iterator:
.. code-block:: nimrod .. code-block:: nimrod
@ -315,7 +315,7 @@ provides. The example uses the built-in ``countup`` iterator:
Echo($i) Echo($i)
The built-in ``$`` operator turns an integer (``int``) and many other types The built-in ``$`` operator turns an integer (``int``) and many other types
into a string. The variable ``i`` is implicitely declared by the ``for`` loop into a string. The variable ``i`` is implicitly declared by the ``for`` loop
and has the type ``int``, because that is what ``countup`` returns. ``i`` runs and has the type ``int``, because that is what ``countup`` returns. ``i`` runs
through the values 1, 2, .., 10. Each value is ``echo``-ed. This code does through the values 1, 2, .., 10. Each value is ``echo``-ed. This code does
the same: the same:
@ -335,7 +335,7 @@ Counting down can be achieved as easily (but is less often needed):
Echo($i) Echo($i)
Since counting up occurs so often in programs, Nimrod has a special syntax that Since counting up occurs so often in programs, Nimrod has a special syntax that
calls the ``countup`` iterator implicitely: calls the ``countup`` iterator implicitly:
.. code-block:: nimrod .. code-block:: nimrod
for i in 1..10: for i in 1..10:
@ -347,7 +347,7 @@ The syntax ``for i in 1..10`` is sugar for ``for i in countup(1, 10)``.
Scopes and the block statement Scopes and the block statement
------------------------------ ------------------------------
Control flow statements have a feature not covered yet: They open a Control flow statements have a feature not covered yet: they open a
new scope. This means that in the following example, ``x`` is not accessible new scope. This means that in the following example, ``x`` is not accessible
outside the loop: outside the loop:
@ -358,7 +358,7 @@ outside the loop:
A while (for) statement introduces an implicit block. Identifiers A while (for) statement introduces an implicit block. Identifiers
are only visible within the block they have been declared. The ``block`` are only visible within the block they have been declared. The ``block``
statement can be used to open a new block explicitely: statement can be used to open a new block explicitly:
.. code-block:: nimrod .. code-block:: nimrod
block myblock: block myblock:
@ -510,11 +510,11 @@ false if he answered "no" (or something similar). A ``return`` statement leaves
the procedure (and therefore the while loop) immediately. The the procedure (and therefore the while loop) immediately. The
``(question: string): bool`` syntax describes that the procedure expects a ``(question: string): bool`` syntax describes that the procedure expects a
parameter named ``question`` of type ``string`` and returns a value of type parameter named ``question`` of type ``string`` and returns a value of type
``bool``. ``Bool`` is a built-in type: The only valid values for ``bool`` are ``bool``. ``Bool`` is a built-in type: the only valid values for ``bool`` are
``true`` and ``false``. ``true`` and ``false``.
The conditions in if or while statements should be of the type ``bool``. The conditions in if or while statements should be of the type ``bool``.
Some terminology: In the example ``question`` is called a (formal) *parameter*, Some terminology: in the example ``question`` is called a (formal) *parameter*,
``"Should I..."`` is called an *argument* that is passed to this parameter. ``"Should I..."`` is called an *argument* that is passed to this parameter.
@ -634,7 +634,7 @@ Nimrod provides the ability to overload procedures similar to C++:
The compiler chooses the most appropriate proc for the ``toString`` calls. How The compiler chooses the most appropriate proc for the ``toString`` calls. How
this overloading resolution algorithm works exactly is not discussed here this overloading resolution algorithm works exactly is not discussed here
(it will be specified in the manual soon). (it will be specified in the manual soon).
However, it does not lead to nasty suprises and is based on a quite simple However, it does not lead to nasty surprises and is based on a quite simple
unification algorithm. Ambiguous calls are reported as errors. unification algorithm. Ambiguous calls are reported as errors.
@ -644,7 +644,7 @@ The Nimrod library makes heavy use of overloading - one reason for this is that
each operator like ``+`` is a just an overloaded proc. The parser lets you each operator like ``+`` is a just an overloaded proc. The parser lets you
use operators in `infix notation` (``a + b``) or `prefix notation` (``+ a``). use operators in `infix notation` (``a + b``) or `prefix notation` (``+ a``).
An infix operator always receives two arguments, a prefix operator always one. An infix operator always receives two arguments, a prefix operator always one.
Postfix operators are not possible, because this would be ambiguous: Does Postfix operators are not possible, because this would be ambiguous: does
``a @ @ b`` mean ``(a) @ (@b)`` or ``(a@) @ (b)``? It always means ``a @ @ b`` mean ``(a) @ (@b)`` or ``(a@) @ (b)``? It always means
``(a) @ (@b)``, because there are no postfix operators in Nimrod. ``(a) @ (@b)``, because there are no postfix operators in Nimrod.
@ -693,7 +693,7 @@ However, this cannot be done for mutually recursive procedures:
Here ``odd`` depends on ``even`` and vice versa. Thus ``even`` needs to be Here ``odd`` depends on ``even`` and vice versa. Thus ``even`` needs to be
introduced to the compiler before it is completely defined. The syntax for introduced to the compiler before it is completely defined. The syntax for
such a `forward declaration` is simple: Just omit the ``=`` and the procedure's such a `forward declaration` is simple: just omit the ``=`` and the procedure's
body. body.
@ -771,7 +771,7 @@ Characters
---------- ----------
The `character type` is named ``char`` in Nimrod. Its size is one byte. The `character type` is named ``char`` in Nimrod. Its size is one byte.
Thus it cannot represent an UTF-8 character, but a part of it. Thus it cannot represent an UTF-8 character, but a part of it.
The reason for this is efficiency: For the overwhelming majority of use-cases, 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 the resulting programs will still handle UTF-8 properly as UTF-8 was specially
designed for this. designed for this.
Character literals are enclosed in single quotes. Character literals are enclosed in single quotes.
@ -795,7 +795,8 @@ terminating zero is no error and often leads to simpler code:
# no need to check whether ``i < len(s)``! # no need to check whether ``i < len(s)``!
... ...
The assignment operator for strings copies the string. The assignment operator for strings copies the string. You can use the ``&``
operator to concatenate strings.
Strings are compared by their lexicographical order. All comparison operators Strings are compared by their lexicographical order. All comparison operators
are available. Per convention, all strings are UTF-8 strings, but this is not are available. Per convention, all strings are UTF-8 strings, but this is not
@ -826,7 +827,7 @@ to mark them to be of another integer type:
y = 0'i8 # y is of type ``int8`` y = 0'i8 # y is of type ``int8``
z = 0'i64 # z is of type ``int64`` z = 0'i64 # z is of type ``int64``
Most often integers are used for couting objects that reside in memory, so Most often integers are used for counting objects that reside in memory, so
``int`` has the same size as a pointer. ``int`` has the same size as a pointer.
The common operators ``+ - * div mod < <= == != > >=`` are defined for The common operators ``+ - * div mod < <= == != > >=`` are defined for
@ -843,7 +844,7 @@ errors. Unsigned operations use the ``%`` suffix as convention:
operation meaning operation meaning
====================== ====================================================== ====================== ======================================================
``a +% b`` unsigned integer addition ``a +% b`` unsigned integer addition
``a -% b`` unsigned integer substraction ``a -% b`` unsigned integer subtraction
``a *% b`` unsigned integer multiplication ``a *% b`` unsigned integer multiplication
``a /% b`` unsigned integer division ``a /% b`` unsigned integer division
``a %% b`` unsigned integer modulo operation ``a %% b`` unsigned integer modulo operation
@ -877,7 +878,7 @@ The common operators ``+ - * / < <= == != > >=`` are defined for
floats and follow the IEEE standard. floats and follow the IEEE standard.
Automatic type conversion in expressions with different kinds Automatic type conversion in expressions with different kinds
of floating point types is performed: The smaller type is of floating point types is performed: the smaller type is
converted to the larger. Integer types are **not** converted to floating point converted to the larger. Integer types are **not** converted to floating point
types automatically and vice versa. The ``toInt`` and ``toFloat`` procs can be types automatically and vice versa. The ``toInt`` and ``toFloat`` procs can be
used for these conversions. used for these conversions.
@ -927,7 +928,7 @@ types can be assigned an explicit ordinal value. However, the ordinal values
have to be in ascending order. A symbol whose ordinal value is not have to be in ascending order. A symbol whose ordinal value is not
explicitly given is assigned the value of the previous symbol + 1. explicitly given is assigned the value of the previous symbol + 1.
An explicit ordered enum can have *wholes*: An explicit ordered enum can have *holes*:
.. code-block:: nimrod .. code-block:: nimrod
type type
@ -937,7 +938,7 @@ An explicit ordered enum can have *wholes*:
Ordinal types Ordinal types
------------- -------------
Enumerations without wholes, integer types, ``char`` and ``bool`` (and Enumerations without holes, integer types, ``char`` and ``bool`` (and
subranges) are called `ordinal`:idx: types. Ordinal types have quite subranges) are called `ordinal`:idx: types. Ordinal types have quite
a few special operations: a few special operations:
@ -979,7 +980,7 @@ subrange types (and vice versa) are allowed.
The ``system`` module defines the important ``natural`` type as The ``system`` module defines the important ``natural`` type as
``range[0..high(int)]`` (``high`` returns the maximal value). Other programming ``range[0..high(int)]`` (``high`` returns the maximal value). Other programming
languages mandate the usage of unsigned integers for natural numbers. This is languages mandate the usage of unsigned integers for natural numbers. This is
often **wrong**: You don't want unsigned arithmetic (which wraps around) just often **wrong**: you don't want unsigned arithmetic (which wraps around) just
because the numbers cannot be negative. Nimrod's ``natural`` type helps to because the numbers cannot be negative. Nimrod's ``natural`` type helps to
avoid this common programming error. avoid this common programming error.
@ -1100,7 +1101,7 @@ position 0. The ``len``, ``low`` and ``high`` operations are available
for open arrays too. Any array with a compatible base type can be passed to for open arrays too. Any array with a compatible base type can be passed to
an openarray parameter, the index type does not matter. an openarray parameter, the index type does not matter.
The openarray type cannot be nested: Multidimensional openarrays are not The openarray type cannot be nested: multidimensional openarrays are not
supported because this is seldom needed and cannot be done efficiently. supported because this is seldom needed and cannot be done efficiently.
An openarray is also a means to implement passing a variable number of An openarray is also a means to implement passing a variable number of
@ -1156,7 +1157,7 @@ integer.
Reference and pointer types Reference and pointer types
--------------------------- ---------------------------
References (similiar to `pointers`:idx: in other programming languages) are a References (similar to `pointers`:idx: in other programming languages) are a
way to introduce many-to-one relationships. This means different references can way to introduce many-to-one relationships. This means different references can
point to and modify the same location in memory. point to and modify the same location in memory.
@ -1199,7 +1200,7 @@ further information.
If a reference points to *nothing*, it has the value ``nil``. If a reference points to *nothing*, it has the value ``nil``.
Special care has to be taken if an untraced object contains traced objects like Special care has to be taken if an untraced object contains traced objects like
traced references, strings or sequences: In order to free everything properly, traced references, strings or sequences: in order to free everything properly,
the built-in procedure ``GCunref`` has to be called before freeing the untraced the built-in procedure ``GCunref`` has to be called before freeing the untraced
memory manually: memory manually:
@ -1221,11 +1222,11 @@ memory manually:
Without the ``GCunref`` call the memory allocated for the ``d.s`` string would Without the ``GCunref`` call the memory allocated for the ``d.s`` string would
never be freed. The example also demonstrates two important features for low 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 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 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 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 TData``. Casting should only be
done if it is unavoidable: It breaks type safety and bugs can lead to done if it is unavoidable: it breaks type safety and bugs can lead to
mysterious crashes. mysterious crashes.
**Note**: The example only works because the memory is initialized with zero **Note**: The example only works because the memory is initialized with zero
@ -1259,7 +1260,7 @@ Example:
forEach(echoItem) forEach(echoItem)
A subtle issue with procedural types is that the calling convention of the A subtle issue with procedural types is that the calling convention of the
procedure influences the type compability: Procedural types are only compatible procedure influences the type compatibility: procedural types are only compatible
if they have the same calling convention. The different calling conventions are if they have the same calling convention. The different calling conventions are
listed in the `user guide <nimrodc.html>`_. listed in the `user guide <nimrodc.html>`_.
@ -1290,7 +1291,7 @@ with an asterisk (``*``) are exported:
The above module exports ``x`` and ``*``, but not ``y``. The above module exports ``x`` and ``*``, but not ``y``.
The top-level statements of a module are executed at the start of the program. The top-level statements of a module are executed at the start of the program.
This can be used to initalize complex data structures for example. This can be used to initialize complex data structures for example.
Each module has a special magic constant ``isMainModule`` that is true if the Each module has a special magic constant ``isMainModule`` that is true if the
module is compiled as the main file. This is very useful to embed tests within module is compiled as the main file. This is very useful to embed tests within
@ -1387,7 +1388,7 @@ exported symbols. An alternative that only imports listed symbols is the
Include statement Include statement
----------------- -----------------
The `include`:idx: statement does something fundametally different than The `include`:idx: statement does something fundametally different than
importing a module: It merely includes the contents of a file. The ``include`` importing a module: it merely includes the contents of a file. The ``include``
statement is useful to split up a large module into several files: statement is useful to split up a large module into several files:
.. code-block:: nimrod .. code-block:: nimrod

View file

@ -11,7 +11,7 @@ Nimrod Tutorial (Part II)
Introduction Introduction
============ ============
"With great power comes great responsibility." -- Spider-man "With great power comes great responsibility." -- Spiderman
This document is a tutorial for the advanced constructs of the *Nimrod* This document is a tutorial for the advanced constructs of the *Nimrod*
programming language. programming language.
@ -33,7 +33,7 @@ Object Oriented Programming
While Nimrod's support for object oriented programming (OOP) is minimalistic, While Nimrod's support for object oriented programming (OOP) is minimalistic,
powerful OOP technics can be used. OOP is seen as *one* way to design a powerful OOP technics can be used. OOP is seen as *one* way to design a
program, not *the only* way. Often a procedural approach leads to simpler program, not *the only* way. Often a procedural approach leads to simpler
and more efficient code. In particular, prefering aggregation over inheritance and more efficient code. In particular, prefering composition over inheritance
is often the better design. is often the better design.
@ -134,7 +134,7 @@ An example:
.. code-block:: nimrod .. code-block:: nimrod
# This is an example how an abstract syntax tree could be modelled in Nimrod # This is an example how an abstract syntax tree could be modeled in Nimrod
type type
TNodeKind = enum # the different node types TNodeKind = enum # the different node types
nkInt, # a leaf with an integer value nkInt, # a leaf with an integer value
@ -176,7 +176,7 @@ bound to a class. This has disadvantages:
* Adding a method to a class the programmer has no control over is * Adding a method to a class the programmer has no control over is
impossible or needs ugly workarounds. impossible or needs ugly workarounds.
* Often it is unclear where the method should belong to: Is * Often it is unclear where the method should belong to: is
``join`` a string method or an array method? ``join`` a string method or an array method?
Nimrod avoids these problems by not assigning methods to a class. All methods Nimrod avoids these problems by not assigning methods to a class. All methods
@ -336,9 +336,9 @@ dispatching:
collide(a, b) # output: 2 collide(a, b) # output: 2
As the example demonstrates, invokation of a multi-method cannot be ambiguous: As the example demonstrates, invocation of a multi-method cannot be ambiguous:
Collide 2 is prefered over collide 1 because the resolution works from left to Collide 2 is preferred over collide 1 because the resolution works from left to
right. Thus ``TUnit, TThing`` is prefered over ``TThing, TUnit``. right. Thus ``TUnit, TThing`` is preferred over ``TThing, TUnit``.
**Perfomance note**: Nimrod does not produce a virtual method table, but **Perfomance note**: Nimrod does not produce a virtual method table, but
generates dispatch trees. This avoids the expensive indirect branch for method generates dispatch trees. This avoids the expensive indirect branch for method
@ -407,7 +407,7 @@ The statements after the ``try`` are executed unless an exception is
raised. Then the appropriate ``except`` part is executed. raised. Then the appropriate ``except`` part is executed.
The empty ``except`` part is executed if there is an exception that is The empty ``except`` part is executed if there is an exception that is
not explicitely listed. It is similiar to an ``else`` part in ``if`` not explicitly listed. It is similar to an ``else`` part in ``if``
statements. statements.
If there is a ``finally`` part, it is always executed after the If there is a ``finally`` part, it is always executed after the
@ -485,7 +485,7 @@ containers:
The example shows a generic binary tree. Depending on context, the brackets are The example shows a generic binary tree. Depending on context, the brackets are
used either to introduce type parameters or to instantiate a generic proc, used either to introduce type parameters or to instantiate a generic proc,
iterator or type. As the example shows, generics work with overloading: The iterator or type. As the example shows, generics work with overloading: the
best match of ``add`` is used. The built-in ``add`` procedure for sequences best match of ``add`` is used. The built-in ``add`` procedure for sequences
is not hidden and used in the ``preorder`` iterator. is not hidden and used in the ``preorder`` iterator.
@ -510,7 +510,7 @@ Example:
assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6)) assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6))
The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact
templates: This has the benefit that if you overload the ``==`` operator, templates: this has the benefit that if you overload the ``==`` operator,
the ``!=`` operator is available automatically and does the right thing. (Except the ``!=`` operator is available automatically and does the right thing. (Except
for IEEE floating point numbers - NaN breaks basic boolean logic.) for IEEE floating point numbers - NaN breaks basic boolean logic.)
@ -532,7 +532,7 @@ simple proc for logging:
x = 4 x = 4
log("x has the value: " & $x) log("x has the value: " & $x)
This code has a shortcoming: If ``debug`` is set to false someday, the quite This code has a shortcoming: if ``debug`` is set to false someday, the quite
expensive ``$`` and ``&`` operations are still performed! (The argument expensive ``$`` and ``&`` operations are still performed! (The argument
evaluation for procedures is *eager*). evaluation for procedures is *eager*).
@ -598,7 +598,7 @@ via a special ``:`` syntax:
In the example the two ``writeln`` statements are bound to the ``actions`` In the example the two ``writeln`` statements are bound to the ``actions``
parameter. The ``withFile`` template contains boilerplate code and helps to parameter. The ``withFile`` template contains boilerplate code and helps to
avoid a common bug: To forget to close the file. Note how the avoid a common bug: to forget to close the file. Note how the
``var fn = filename`` statement ensures that ``filename`` is evaluated only ``var fn = filename`` statement ensures that ``filename`` is evaluated only
once. once.
@ -606,7 +606,7 @@ once.
Macros Macros
====== ======
Macros enable advanced compile-time code tranformations, but they Macros enable advanced compile-time code transformations, but they
cannot change Nimrod's syntax. However, this is no real restriction because cannot change Nimrod's syntax. However, this is no real restriction because
Nimrod's syntax is flexible enough anyway. Nimrod's syntax is flexible enough anyway.
@ -676,13 +676,13 @@ Statement Macros
Statement macros are defined just as expression macros. However, they are Statement macros are defined just as expression macros. However, they are
invoked by an expression following a colon. invoked by an expression following a colon.
The following example outlines a macro that generates a lexical analyser from The following example outlines a macro that generates a lexical analyzer from
regular expressions: regular expressions:
.. code-block:: nimrod .. code-block:: nimrod
macro case_token(n: stmt): stmt = macro case_token(n: stmt): stmt =
# creates a lexical analyser from regular expressions # creates a lexical analyzer from regular expressions
# ... (implementation is an exercise for the reader :-) # ... (implementation is an exercise for the reader :-)
nil nil

64
tests/tromans.nim Executable file
View file

@ -0,0 +1,64 @@
import
math, strutils
## Convert an integer to a Roman numeral
# See http://en.wikipedia.org/wiki/Roman_numerals for reference
proc raiseInvalidValue(msg: string) {.noreturn.} =
# Yes, we really need a shorthand for this code...
var e: ref EInvalidValue
new(e)
e.msg = msg
raise e
# I should use a class, perhaps.
# --> No. Why introduce additional state into such a simple and nice
# interface? State is evil. :D
proc ConvertRomanToDecimal(romanVal: string): int =
result = 0
var prevVal = 0
for i in countdown(romanVal.len - 1, 0):
var val = 0
case romanVal[i]
of 'I', 'i': val = 1
of 'V', 'v': val = 5
of 'X', 'x': val = 10
of 'L', 'l': val = 50
of 'C', 'c': val = 100
of 'D', 'd': val = 500
of 'M', 'm': val = 1000
else: raiseInvalidValue("Incorrect character in roman numeral! (" &
$romanVal[i] & ")")
if val >= prevVal:
inc(result, val)
else:
dec(result, val)
prevVal = val
proc ConvertDecimalToRoman(decValParam: int): string =
# Apparently numbers cannot be above 4000
# Well, they can be (using overbar or parenthesis notation)
# but I see little interest (beside coding challenge) in coding them as
# we rarely use huge Roman numeral.
const romanComposites = [
("M", 1000), ("CM", 900),
("D", 500), ("CD", 400), ("C", 100),
("XC", 90), ("L", 50), ("XL", 40), ("X", 10), ("IX", 9),
("V", 5), ("IV", 4), ("I", 1)]
if decValParam < 1 or decValParam > 3999:
raiseInvalidValue("number not representable")
result = ""
var decVal = decValParam
for key, val in items(romanComposites):
while decVal >= val:
dec(decVal, val)
result.add(key)
randomize()
for i in 1 .. 10:
var rnd = 1 + random(3990)
var roman = ConvertDecimalToRoman(rnd)
var decimal = ConvertRomanToDecimal(roman)
echo("$# => $# => $#" % [ $rnd, roman, $decimal ])