fixed typos in documentation
This commit is contained in:
parent
63e9a88c1f
commit
281609c358
6 changed files with 316 additions and 248 deletions
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
103
doc/manual.txt
103
doc/manual.txt
|
|
@ -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.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
85
doc/tut1.txt
85
doc/tut1.txt
|
|
@ -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
|
||||||
|
|
|
||||||
30
doc/tut2.txt
30
doc/tut2.txt
|
|
@ -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
64
tests/tromans.nim
Executable 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 ])
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue