big rename
This commit is contained in:
parent
15a7bcc89f
commit
11b6958755
98 changed files with 2491 additions and 2341 deletions
465
doc/manual.txt
465
doc/manual.txt
File diff suppressed because it is too large
Load diff
|
|
@ -180,7 +180,7 @@ So it is not necessary to write ``peg" 'abc' "`` in the above example.
|
|||
Examples
|
||||
--------
|
||||
|
||||
Check if `s` matches Nimrod's "while" keyword:
|
||||
Check if `s` matches Nim's "while" keyword:
|
||||
|
||||
.. code-block:: nimrod
|
||||
s =~ peg" y'while'"
|
||||
|
|
@ -212,7 +212,7 @@ example ``*`` should not be greedy, so ``\[.*?\]`` should be used instead.
|
|||
|
||||
PEG construction
|
||||
----------------
|
||||
There are two ways to construct a PEG in Nimrod code:
|
||||
There are two ways to construct a PEG in Nim code:
|
||||
(1) Parsing a string into an AST which consists of `TPeg` nodes with the
|
||||
`peg` proc.
|
||||
(2) Constructing the AST directly with proc calls. This method does not
|
||||
|
|
|
|||
258
doc/tut1.txt
258
doc/tut1.txt
|
|
@ -1,9 +1,9 @@
|
|||
========================
|
||||
Nimrod Tutorial (Part I)
|
||||
========================
|
||||
=====================
|
||||
Nim Tutorial (Part I)
|
||||
=====================
|
||||
|
||||
:Author: Andreas Rumpf
|
||||
:Version: |nimrodversion|
|
||||
:Version: |nimversion|
|
||||
|
||||
.. contents::
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ Introduction
|
|||
</p></blockquote>
|
||||
|
||||
|
||||
This document is a tutorial for the programming language *Nimrod*.
|
||||
This document is a tutorial for the programming language *Nim*.
|
||||
This tutorial assumes that you are familiar with basic programming concepts
|
||||
like variables, types or statements but is kept very basic. The `manual
|
||||
<manual.html>`_ contains many more examples of the advanced language features.
|
||||
|
|
@ -28,7 +28,7 @@ The first program
|
|||
|
||||
We start the tour with a modified "hello world" program:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
.. code-block:: Nim
|
||||
# This is a comment
|
||||
echo("What's your name? ")
|
||||
var name: string = readLine(stdin)
|
||||
|
|
@ -37,30 +37,30 @@ We start the tour with a modified "hello world" program:
|
|||
|
||||
Save this code to the file "greetings.nim". Now compile and run it::
|
||||
|
||||
nimrod compile --run greetings.nim
|
||||
nim compile --run greetings.nim
|
||||
|
||||
With the ``--run`` `switch <nimrodc.html#command-line-switches>`_ Nimrod
|
||||
With the ``--run`` `switch <nimc.html#command-line-switches>`_ Nim
|
||||
executes the file automatically after compilation. You can give your program
|
||||
command line arguments by appending them after the filename::
|
||||
|
||||
nimrod compile --run greetings.nim arg1 arg2
|
||||
nim compile --run greetings.nim arg1 arg2
|
||||
|
||||
Commonly used commands and switches have abbreviations, so you can also use::
|
||||
|
||||
nimrod c -r greetings.nim
|
||||
nim c -r greetings.nim
|
||||
|
||||
To compile a release version use::
|
||||
|
||||
nimrod c -d:release greetings.nim
|
||||
nim c -d:release greetings.nim
|
||||
|
||||
By default the Nimrod compiler generates a large amount of runtime checks
|
||||
By default the Nim compiler generates a large amount of runtime checks
|
||||
aiming for your debugging pleasure. With ``-d:release`` these checks are
|
||||
`turned off and optimizations are turned on
|
||||
<nimrodc.html#compile-time-symbols>`_.
|
||||
<nimc.html#compile-time-symbols>`_.
|
||||
|
||||
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
|
||||
starts. Indentation is Nimrod's way of grouping statements. Indentation is
|
||||
starts. Indentation is Nim's way of grouping statements. Indentation is
|
||||
done with spaces only, tabulators are not allowed.
|
||||
|
||||
String literals are enclosed in double quotes. The ``var`` statement declares
|
||||
|
|
@ -70,11 +70,11 @@ compiler knows that `readLine <system.html#readLine,TFile>`_ returns a string,
|
|||
you can leave out the type in the declaration (this is called `local type
|
||||
inference`:idx:). So this will work too:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
.. code-block:: Nim
|
||||
var name = readLine(stdin)
|
||||
|
||||
Note that this is basically the only form of type inference that exists in
|
||||
Nimrod: it is a good compromise between brevity and readability.
|
||||
Nim: it is a good compromise between brevity and readability.
|
||||
|
||||
The "hello world" program contains several identifiers that are already known
|
||||
to the compiler: ``echo``, `readLine <system.html#readLine,TFile>`_, etc.
|
||||
|
|
@ -85,8 +85,8 @@ imported by any other module.
|
|||
Lexical elements
|
||||
================
|
||||
|
||||
Let us look at Nimrod's lexical elements in more detail: like other
|
||||
programming languages Nimrod consists of (string) literals, identifiers,
|
||||
Let us look at Nim's lexical elements in more detail: like other
|
||||
programming languages Nim consists of (string) literals, identifiers,
|
||||
keywords, comments, operators, and other punctuation marks.
|
||||
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ String literals are enclosed in double quotes; character literals in single
|
|||
quotes. Special characters are escaped with ``\``: ``\n`` means newline, ``\t``
|
||||
means tabulator, etc. There are also *raw* string literals:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
.. code-block:: Nim
|
||||
r"C:\program files\nim"
|
||||
|
||||
In raw literals the backslash is not an escape character.
|
||||
|
|
@ -115,7 +115,7 @@ Comments start anywhere outside a string or character literal with the
|
|||
hash character ``#``. Documentation comments start with ``##``. Multiline
|
||||
comments need to be aligned at the same column:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
i = 0 # This is a single comment over multiple lines belonging to the
|
||||
# assignment statement.
|
||||
|
|
@ -128,7 +128,7 @@ comments need to be aligned at the same column:
|
|||
The alignment requirement does not hold if the preceding comment piece ends in
|
||||
a backslash:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
TMyObject {.final, pure, acyclic.} = object # comment continues: \
|
||||
# we have lots of space here to comment 'TMyObject'.
|
||||
|
|
@ -151,15 +151,15 @@ the syntax, watch their indentation:
|
|||
**Note**: To comment out a large piece of code, it is often better to use a
|
||||
``when false:`` statement.
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
when false:
|
||||
brokenCode()
|
||||
|
||||
Another option is to use the `discard statement`_ together with *long string
|
||||
literals* to create block comments:
|
||||
|
||||
.. code-block:: nimrod
|
||||
discard """ You can have any Nimrod code text commented
|
||||
.. code-block:: nim
|
||||
discard """ You can have any Nim code text commented
|
||||
out inside this with no indentation restrictions.
|
||||
yes("May I ask a pointless question?") """
|
||||
|
||||
|
|
@ -204,7 +204,7 @@ to a storage location:
|
|||
|
||||
``=`` is the *assignment operator*. The assignment operator cannot be
|
||||
overloaded, overwritten or forbidden, but this might change in a future version
|
||||
of Nimrod. You can declare multiple variables with a single assignment
|
||||
of Nim. You can declare multiple variables with a single assignment
|
||||
statement and all the variables will have the same value:
|
||||
|
||||
.. code-block::
|
||||
|
|
@ -229,7 +229,7 @@ Constants are symbols which are bound to a value. The constant's value
|
|||
cannot change. The compiler must be able to evaluate the expression in a
|
||||
constant declaration at compile time:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
const x = "abc" # the constant x contains the string "abc"
|
||||
|
||||
Indentation can be used after the ``const`` keyword to list a whole section of
|
||||
|
|
@ -277,7 +277,7 @@ If statement
|
|||
|
||||
The if statement is one way to branch the control flow:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
let name = readLine(stdin)
|
||||
if name == "":
|
||||
echo("Poor soul, you lost your name?")
|
||||
|
|
@ -298,7 +298,7 @@ Case statement
|
|||
Another way to branch is provided by the case statement. A case statement is
|
||||
a multi-branch:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
let name = readLine(stdin)
|
||||
case name
|
||||
of "":
|
||||
|
|
@ -317,7 +317,7 @@ The case statement can deal with integers, other ordinal types and strings.
|
|||
(What an ordinal type is will be explained soon.)
|
||||
For integers or other ordinal types value ranges are also possible:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# this statement will be explained later:
|
||||
from strutils import parseInt
|
||||
|
||||
|
|
@ -333,7 +333,7 @@ every value that ``n`` may contain, but the code only handles the values
|
|||
(though it is possible thanks to the range notation), we fix this by telling
|
||||
the compiler that for every other value nothing should be done:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
...
|
||||
case n
|
||||
of 0..2, 4..7: echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}")
|
||||
|
|
@ -355,7 +355,7 @@ While statement
|
|||
|
||||
The while statement is a simple looping construct:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
echo("What's your name? ")
|
||||
var name = readLine(stdin)
|
||||
|
|
@ -375,7 +375,7 @@ The ``for`` statement is a construct to loop over any element an *iterator*
|
|||
provides. The example uses the built-in `countup <system.html#countup>`_
|
||||
iterator:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
echo("Counting to ten: ")
|
||||
for i in countup(1, 10):
|
||||
echo($i)
|
||||
|
|
@ -387,7 +387,7 @@ other types into a string. The variable ``i`` is implicitly declared by the
|
|||
<system.html#countup>`_ returns. ``i`` runs through the values 1, 2, .., 10.
|
||||
Each value is ``echo``-ed. This code does the same:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
echo("Counting to 10: ")
|
||||
var i = 1
|
||||
while i <= 10:
|
||||
|
|
@ -397,16 +397,16 @@ Each value is ``echo``-ed. This code does the same:
|
|||
|
||||
Counting down can be achieved as easily (but is less often needed):
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
echo("Counting down from 10 to 1: ")
|
||||
for i in countdown(10, 1):
|
||||
echo($i)
|
||||
# --> Outputs 10 9 8 7 6 5 4 3 2 1 on different lines
|
||||
|
||||
Since counting up occurs so often in programs, Nimrod also has a `..
|
||||
Since counting up occurs so often in programs, Nim also has a `..
|
||||
<system.html#...i,S,T>`_ iterator that does the same:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
for i in 1..10:
|
||||
...
|
||||
|
||||
|
|
@ -417,7 +417,7 @@ 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
|
||||
outside the loop:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
while false:
|
||||
var x = "hi"
|
||||
echo(x) # does not work
|
||||
|
|
@ -426,7 +426,7 @@ A while (for) statement introduces an implicit block. Identifiers
|
|||
are only visible within the block they have been declared. The ``block``
|
||||
statement can be used to open a new block explicitly:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
block myblock:
|
||||
var x = "hi"
|
||||
echo(x) # does not work either
|
||||
|
|
@ -440,7 +440,7 @@ A block can be left prematurely with a ``break`` statement. The break statement
|
|||
can leave a ``while``, ``for``, or a ``block`` statement. It leaves the
|
||||
innermost construct, unless a label of a block is given:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
block myblock:
|
||||
echo("entering block")
|
||||
while true:
|
||||
|
|
@ -461,7 +461,7 @@ Continue statement
|
|||
Like in many other programming languages, a ``continue`` statement starts
|
||||
the next iteration immediately:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
while true:
|
||||
let x = readLine(stdin)
|
||||
if x == "": continue
|
||||
|
|
@ -473,7 +473,7 @@ When statement
|
|||
|
||||
Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
when system.hostOS == "windows":
|
||||
echo("running on Windows!")
|
||||
|
|
@ -504,17 +504,17 @@ possible.
|
|||
Statements and indentation
|
||||
==========================
|
||||
|
||||
Now that we covered the basic control flow statements, let's return to Nimrod
|
||||
Now that we covered the basic control flow statements, let's return to Nim
|
||||
indentation rules.
|
||||
|
||||
In Nimrod there is a distinction between *simple statements* and *complex
|
||||
In Nim there is a distinction between *simple statements* and *complex
|
||||
statements*. *Simple statements* cannot contain other statements:
|
||||
Assignment, procedure calls or the ``return`` statement belong to the simple
|
||||
statements. *Complex statements* like ``if``, ``when``, ``for``, ``while`` can
|
||||
contain other statements. To avoid ambiguities, complex statements always have
|
||||
to be indented, but single simple statements do not:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# no indentation needed for single assignment statement:
|
||||
if x: x = false
|
||||
|
||||
|
|
@ -535,7 +535,7 @@ to be indented, but single simple statements do not:
|
|||
condition in an if statement is an example for an expression. Expressions can
|
||||
contain indentation at certain places for better readability:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
if thisIsaLongCondition() and
|
||||
thisIsAnotherLongCondition(1,
|
||||
|
|
@ -548,7 +548,7 @@ an open parenthesis and after commas.
|
|||
With parenthesis and semicolons ``(;)`` you can use statements where only
|
||||
an expression is allowed:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# computes fac(4) at compile time:
|
||||
const fac4 = (var x = 1; for i in 1..4: x *= i; x)
|
||||
|
||||
|
|
@ -558,10 +558,10 @@ Procedures
|
|||
|
||||
To define new commands like `echo <system.html#echo>`_ and `readLine
|
||||
<system.html#readLine,TFile>`_ in the examples, the concept of a `procedure`
|
||||
is needed. (Some languages call them *methods* or *functions*.) In Nimrod new
|
||||
is needed. (Some languages call them *methods* or *functions*.) In Nim new
|
||||
procedures are defined with the ``proc`` keyword:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc yes(question: string): bool =
|
||||
echo(question, " (y/n)")
|
||||
while true:
|
||||
|
|
@ -597,7 +597,7 @@ shorthand for ``return result``. The ``result`` value is always returned
|
|||
automatically at the end a procedure if there is no ``return`` statement at
|
||||
the exit.
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc sumTillNegative(x: varargs[int]): int =
|
||||
for i in x:
|
||||
if i < 0:
|
||||
|
|
@ -624,7 +624,7 @@ most efficient way. If a mutable variable is needed inside the procedure, it has
|
|||
to be declared with ``var`` in the procedure body. Shadowing the parameter name
|
||||
is possible, and actually an idiom:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc printSeq(s: seq, nprinted: int = -1) =
|
||||
var nprinted = if nprinted == -1: s.len else: min(nprinted, s.len)
|
||||
for i in 0 .. <nprinted:
|
||||
|
|
@ -633,7 +633,7 @@ is possible, and actually an idiom:
|
|||
If the procedure needs to modify the argument for the
|
||||
caller, a ``var`` parameter can be used:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc divmod(a, b: int; res, remainder: var int) =
|
||||
res = a div b # integer division
|
||||
remainder = a mod b # integer modulo operation
|
||||
|
|
@ -653,17 +653,17 @@ a tuple as a return value instead of using var parameters.
|
|||
Discard statement
|
||||
-----------------
|
||||
To call a procedure that returns a value just for its side effects and ignoring
|
||||
its return value, a ``discard`` statement **has** to be used. Nimrod does not
|
||||
its return value, a ``discard`` statement **has** to be used. Nim does not
|
||||
allow to silently throw away a return value:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
discard yes("May I ask a pointless question?")
|
||||
|
||||
|
||||
The return value can be ignored implicitly if the called proc/iterator has
|
||||
been declared with the ``discardable`` pragma:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc p(x, y: int): int {.discardable.} =
|
||||
return x + y
|
||||
|
||||
|
|
@ -681,7 +681,7 @@ parameters appear. This is especially true for procedures that construct a
|
|||
complex data type. Therefore the arguments to a procedure can be named, so
|
||||
that it is clear which argument belongs to which parameter:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc createWindow(x, y, width, height: int; title: string;
|
||||
show: bool): Window =
|
||||
...
|
||||
|
|
@ -693,7 +693,7 @@ Now that we use named arguments to call ``createWindow`` the argument order
|
|||
does not matter anymore. Mixing named arguments with ordered arguments is
|
||||
also possible, but not very readable:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
var w = createWindow(0, 0, title = "My Application",
|
||||
height = 600, width = 800, true)
|
||||
|
||||
|
|
@ -706,7 +706,7 @@ To make the ``createWindow`` proc easier to use it should provide `default
|
|||
values`, these are values that are used as arguments if the caller does not
|
||||
specify them:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc createWindow(x = 0, y = 0, width = 500, height = 700,
|
||||
title = "unknown",
|
||||
show = true): Window =
|
||||
|
|
@ -723,9 +723,9 @@ no need to write ``title: string = "unknown"``, for example.
|
|||
|
||||
Overloaded procedures
|
||||
---------------------
|
||||
Nimrod provides the ability to overload procedures similar to C++:
|
||||
Nim provides the ability to overload procedures similar to C++:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc toString(x: int): string = ...
|
||||
proc toString(x: bool): string =
|
||||
if x: result = "true"
|
||||
|
|
@ -735,7 +735,7 @@ Nimrod provides the ability to overload procedures similar to C++:
|
|||
echo(toString(true)) # calls the toString(x: bool) proc
|
||||
|
||||
(Note that ``toString`` is usually the `$ <system.html#$>`_ operator in
|
||||
Nimrod.) The compiler chooses the most appropriate proc for the ``toString``
|
||||
Nim.) The compiler chooses the most appropriate proc for the ``toString``
|
||||
calls. How this overloading resolution algorithm works exactly is not
|
||||
discussed here (it will be specified in the manual soon). However, it does
|
||||
not lead to nasty surprises and is based on a quite simple unification
|
||||
|
|
@ -744,13 +744,13 @@ algorithm. Ambiguous calls are reported as errors.
|
|||
|
||||
Operators
|
||||
---------
|
||||
The Nimrod library makes heavy use of overloading - one reason for this is that
|
||||
The Nim 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
|
||||
use operators in `infix notation` (``a + b``) or `prefix notation` (``+ a``).
|
||||
An infix operator always receives two arguments, a prefix operator always one.
|
||||
Postfix operators are not possible, because this would be ambiguous: does
|
||||
``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 Nim.
|
||||
|
||||
Apart from a few built-in keyword operators such as ``and``, ``or``, ``not``,
|
||||
operators always consist of these characters:
|
||||
|
|
@ -764,7 +764,7 @@ can be found in the manual.
|
|||
|
||||
To define a new operator enclose the operator in backticks "``":
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc `$` (x: myDataType): string = ...
|
||||
# now the $ operator also works with myDataType, overloading resolution
|
||||
# ensures that $ works for built-in types just like before
|
||||
|
|
@ -772,7 +772,7 @@ To define a new operator enclose the operator in backticks "``":
|
|||
The "``" notation can also be used to call an operator just like any other
|
||||
procedure:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
if `==`( `+`(3, 4), 7): echo("True")
|
||||
|
||||
|
||||
|
|
@ -783,7 +783,7 @@ Every variable, procedure, etc. needs to be declared before it can be used.
|
|||
(The reason for this is compilation efficiency.)
|
||||
However, this cannot be done for mutually recursive procedures:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# forward declaration:
|
||||
proc even(n: int): bool
|
||||
|
||||
|
|
@ -810,7 +810,7 @@ Iterators
|
|||
|
||||
Let's return to the boring counting example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
echo("Counting to ten: ")
|
||||
for i in countup(1, 10):
|
||||
echo($i)
|
||||
|
|
@ -818,7 +818,7 @@ Let's return to the boring counting example:
|
|||
Can a `countup <system.html#countup>`_ proc be written that supports this
|
||||
loop? Lets try:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc countup(a, b: int): int =
|
||||
var res = a
|
||||
while res <= b:
|
||||
|
|
@ -831,7 +831,7 @@ finished. This *return and continue* is called a `yield` statement. Now
|
|||
the only thing left to do is to replace the ``proc`` keyword by ``iterator``
|
||||
and there it is - our first iterator:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
iterator countup(a, b: int): int =
|
||||
var res = a
|
||||
while res <= b:
|
||||
|
|
@ -868,7 +868,7 @@ that are available for them in detail.
|
|||
Booleans
|
||||
--------
|
||||
|
||||
The boolean type is named ``bool`` in Nimrod and consists of the two
|
||||
The boolean type is named ``bool`` in Nim and consists of the two
|
||||
pre-defined values ``true`` and ``false``. Conditions in while,
|
||||
if, elif, when statements need to be of type bool.
|
||||
|
||||
|
|
@ -876,7 +876,7 @@ The operators ``not, and, or, xor, <, <=, >, >=, !=, ==`` are defined
|
|||
for the bool type. The ``and`` and ``or`` operators perform short-cut
|
||||
evaluation. Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
while p != nil and p.name != "xyz":
|
||||
# p.name is not evaluated if p == nil
|
||||
|
|
@ -885,7 +885,7 @@ evaluation. Example:
|
|||
|
||||
Characters
|
||||
----------
|
||||
The `character type` is named ``char`` in Nimrod. Its size is one byte.
|
||||
The `character type` is named ``char`` in Nim. Its size is one byte.
|
||||
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 resulting programs will still handle UTF-8 properly as UTF-8 was specially
|
||||
|
|
@ -900,13 +900,13 @@ Converting from an integer to a ``char`` is done with the ``chr`` proc.
|
|||
|
||||
Strings
|
||||
-------
|
||||
String variables in Nimrod are **mutable**, so appending to a string
|
||||
is quite efficient. Strings in Nimrod are both zero-terminated and have a
|
||||
String variables in Nim are **mutable**, so appending to a string
|
||||
is quite efficient. Strings in Nim are both zero-terminated and have a
|
||||
length field. One can retrieve a string's length with the builtin ``len``
|
||||
procedure; the length never counts the terminating zero. Accessing the
|
||||
terminating zero is no error and often leads to simpler code:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
if s[i] == 'a' and s[i+1] == 'b':
|
||||
# no need to check whether ``i < len(s)``!
|
||||
...
|
||||
|
|
@ -929,14 +929,14 @@ object on the heap, so there is a trade-off to be made here.
|
|||
|
||||
Integers
|
||||
--------
|
||||
Nimrod has these integer types built-in:
|
||||
Nim has these integer types built-in:
|
||||
``int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64``.
|
||||
|
||||
The default integer type is ``int``. Integer literals can have a *type suffix*
|
||||
to mark them to be of another integer type:
|
||||
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
let
|
||||
x = 0 # x is of type ``int``
|
||||
y = 0'i8 # y is of type ``int8``
|
||||
|
|
@ -964,7 +964,7 @@ cannot be detected at compile time).
|
|||
|
||||
Floats
|
||||
------
|
||||
Nimrod has these floating point types built-in: ``float float32 float64``.
|
||||
Nim has these floating point types built-in: ``float float32 float64``.
|
||||
|
||||
The default float type is ``float``. In the current implementation,
|
||||
``float`` is always 64 bit wide.
|
||||
|
|
@ -972,7 +972,7 @@ The default float type is ``float``. In the current implementation,
|
|||
Float literals can have a *type suffix* to mark them to be of another float
|
||||
type:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
var
|
||||
x = 0.0 # x is of type ``float``
|
||||
y = 0.0'f32 # y is of type ``float32``
|
||||
|
|
@ -1001,11 +1001,11 @@ having to write its ``$`` operator. You can use then the `repr
|
|||
graphs with cycles. The following example shows that even for basic types
|
||||
there is a difference between the ``$`` and ``repr`` outputs:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
var
|
||||
myBool = true
|
||||
myCharacter = 'n'
|
||||
myString = "nimrod"
|
||||
myString = "nim"
|
||||
myInteger = 42
|
||||
myFloat = 3.14
|
||||
echo($myBool, ":", repr(myBool))
|
||||
|
|
@ -1013,7 +1013,7 @@ there is a difference between the ``$`` and ``repr`` outputs:
|
|||
echo($myCharacter, ":", repr(myCharacter))
|
||||
# --> n:'n'
|
||||
echo($myString, ":", repr(myString))
|
||||
# --> nimrod:0x10fa8c050"nimrod"
|
||||
# --> nim:0x10fa8c050"nim"
|
||||
echo($myInteger, ":", repr(myInteger))
|
||||
# --> 42:42
|
||||
echo($myFloat, ":", repr(myFloat))
|
||||
|
|
@ -1023,9 +1023,9 @@ there is a difference between the ``$`` and ``repr`` outputs:
|
|||
Advanced types
|
||||
==============
|
||||
|
||||
In Nimrod new types can be defined within a ``type`` statement:
|
||||
In Nim new types can be defined within a ``type`` statement:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
biggestInt = int64 # biggest integer type that is available
|
||||
biggestFloat = float64 # biggest float type that is available
|
||||
|
|
@ -1041,7 +1041,7 @@ limited set. This set consists of ordered symbols. Each symbol is mapped
|
|||
to an integer value internally. The first symbol is represented
|
||||
at runtime by 0, the second by 1 and so on. Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
type
|
||||
TDirection = enum
|
||||
|
|
@ -1050,7 +1050,7 @@ at runtime by 0, the second by 1 and so on. Example:
|
|||
var x = south # `x` is of type `TDirection`; its value is `south`
|
||||
echo($x) # writes "south" to `stdout`
|
||||
|
||||
(To prefix a new type with the letter ``T`` is a convention in Nimrod.)
|
||||
(To prefix a new type with the letter ``T`` is a convention in Nim.)
|
||||
All comparison operators can be used with enumeration types.
|
||||
|
||||
An enumeration's symbol can be qualified to avoid ambiguities:
|
||||
|
|
@ -1066,7 +1066,7 @@ explicitly given is assigned the value of the previous symbol + 1.
|
|||
|
||||
An explicit ordered enum can have *holes*:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
TMyEnum = enum
|
||||
a = 2, b = 4, c = 89
|
||||
|
|
@ -1104,7 +1104,7 @@ Subranges
|
|||
A subrange type is a range of values from an integer or enumeration type
|
||||
(the base type). Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
TSubrange = range[0..5]
|
||||
|
||||
|
|
@ -1119,7 +1119,7 @@ type as ``range[0..high(int)]`` (`high <system.html#high>`_ returns the
|
|||
maximal value). Other programming languages mandate the usage of unsigned
|
||||
integers for natural numbers. This is often **wrong**: you don't want unsigned
|
||||
arithmetic (which wraps around) just because the numbers cannot be negative.
|
||||
Nimrod's ``Natural`` type helps to avoid this common programming error.
|
||||
Nim's ``Natural`` type helps to avoid this common programming error.
|
||||
|
||||
|
||||
Sets
|
||||
|
|
@ -1134,7 +1134,7 @@ the array has the same type. The array's index type can be any ordinal type.
|
|||
|
||||
Arrays can be constructed via ``[]``:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
type
|
||||
TIntArray = array[0..5, int] # an array that is indexed with 0..5
|
||||
|
|
@ -1149,14 +1149,14 @@ Array access is always bounds checked (at compile-time or at runtime). These
|
|||
checks can be disabled via pragmas or invoking the compiler with the
|
||||
``--bound_checks:off`` command line switch.
|
||||
|
||||
Arrays are value types, like any other Nimrod type. The assignment operator
|
||||
Arrays are value types, like any other Nim type. The assignment operator
|
||||
copies the whole array contents.
|
||||
|
||||
The built-in `len <system.html#len,TOpenArray>`_ proc returns the array's
|
||||
length. `low(a) <system.html#low>`_ returns the lowest valid index for the
|
||||
array `a` and `high(a) <system.html#high>`_ the highest valid index.
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
TDirection = enum
|
||||
north, east, south, west
|
||||
|
|
@ -1175,13 +1175,13 @@ array `a` and `high(a) <system.html#high>`_ the highest valid index.
|
|||
|
||||
The syntax for nested arrays (multidimensional) in other languages is a matter
|
||||
of appending more brackets because usually each dimension is restricted to the
|
||||
same index type as the others. In nimrod you can have different dimensions with
|
||||
same index type as the others. In Nim you can have different dimensions with
|
||||
different index types, so the nesting syntax is slightly different. Building on
|
||||
the previous example where a level is defined as an array of enums indexed by
|
||||
yet another enum, we can add the following lines to add a light tower type
|
||||
subdivided in height levels accessed through their integer index:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
TLightTower = array[1..10, TLevelSetting]
|
||||
var
|
||||
|
|
@ -1200,14 +1200,14 @@ length. Another way of defining the ``TLightTower`` to show better its
|
|||
nested nature would be to omit the previous definition of the ``TLevelSetting``
|
||||
type and instead write it embedded directly as the type of the first dimension:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
TLightTower = array[1..10, array[north..west, TBlinkLights]]
|
||||
|
||||
It is quite frequent to have arrays start at zero, so there's a shortcut syntax
|
||||
to specify a range from zero to the specified index minus one:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
TIntArray = array[0..5, int] # an array that is indexed with 0..5
|
||||
TQuickArray = array[6, int] # an array that is indexed with 0..5
|
||||
|
|
@ -1239,7 +1239,7 @@ A sequence may be passed to an openarray parameter.
|
|||
|
||||
Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
var
|
||||
x: seq[int] # a sequence of integers
|
||||
|
|
@ -1261,7 +1261,7 @@ value. Here the ``for`` statement is looping over the results from the
|
|||
`pairs() <system.html#pairs.i,seq[T]>`_ iterator from the `system
|
||||
<system.html>`_ module. Examples:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
for i in @[3, 4, 5]:
|
||||
echo($i)
|
||||
# --> 3
|
||||
|
|
@ -1299,7 +1299,7 @@ also a means to implement passing a variable number of
|
|||
arguments to a procedure. The compiler converts the list of arguments
|
||||
to an array automatically:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc myWriteln(f: TFile, a: varargs[string]) =
|
||||
for s in items(a):
|
||||
write(f, s)
|
||||
|
|
@ -1313,7 +1313,7 @@ This transformation is only done if the varargs parameter is the
|
|||
last parameter in the procedure header. It is also possible to perform
|
||||
type conversions in this context:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc myWriteln(f: TFile, a: varargs[string, `$`]) =
|
||||
for s in items(a):
|
||||
write(f, s)
|
||||
|
|
@ -1336,10 +1336,10 @@ context. A slice is just an object of type TSlice which contains two bounds,
|
|||
`a` and `b`. By itself a slice is not very useful, but other collection types
|
||||
define operators which accept TSlice objects to define ranges.
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
var
|
||||
a = "Nimrod is a progamming language"
|
||||
a = "Nim is a progamming language"
|
||||
b = "Slices are useless."
|
||||
|
||||
echo a[10..15] # --> 'a prog'
|
||||
|
|
@ -1366,7 +1366,7 @@ The assignment operator for tuples copies each component. The notation
|
|||
``t[i]`` to access the ``i``'th field. Here ``i`` needs to be a constant
|
||||
integer.
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
type
|
||||
TPerson = tuple[name: string, age: int] # type representing a person:
|
||||
|
|
@ -1411,19 +1411,19 @@ use parenthesis around the values you want to assign the unpacking to,
|
|||
otherwise you will be assigning the same value to all the individual
|
||||
variables! Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
import os
|
||||
|
||||
let
|
||||
path = "usr/local/nimrodc.html"
|
||||
path = "usr/local/nimc.html"
|
||||
(dir, name, ext) = splitFile(path)
|
||||
baddir, badname, badext = splitFile(path)
|
||||
echo dir # outputs `usr/local`
|
||||
echo name # outputs `nimrodc`
|
||||
echo name # outputs `nimc`
|
||||
echo ext # outputs `.html`
|
||||
# All the following output the same line:
|
||||
# `(dir: usr/local, name: nimrodc, ext: .html)`
|
||||
# `(dir: usr/local, name: nimc, ext: .html)`
|
||||
echo baddir
|
||||
echo badname
|
||||
echo badext
|
||||
|
|
@ -1431,12 +1431,12 @@ variables! Example:
|
|||
Tuple unpacking **only** works in ``var`` or ``let`` blocks. The following code
|
||||
won't compile:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
import os
|
||||
|
||||
var
|
||||
path = "usr/local/nimrodc.html"
|
||||
path = "usr/local/nimc.html"
|
||||
dir, name, ext = ""
|
||||
|
||||
(dir, name, ext) = splitFile(path)
|
||||
|
|
@ -1449,7 +1449,7 @@ References (similar to pointers in other programming languages) are a
|
|||
way to introduce many-to-one relationships. This means different references can
|
||||
point to and modify the same location in memory.
|
||||
|
||||
Nimrod distinguishes between `traced`:idx: and `untraced`:idx: references.
|
||||
Nim distinguishes between `traced`:idx: and `untraced`:idx: references.
|
||||
Untraced references are also called *pointers*. Traced references point to
|
||||
objects of a garbage collected heap, untraced references point to
|
||||
manually allocated objects or to objects somewhere else in memory. Thus
|
||||
|
|
@ -1464,7 +1464,7 @@ meaning to retrieve the item the reference points to. The ``.`` (access a
|
|||
tuple/object field operator) and ``[]`` (array/string/sequence index operator)
|
||||
operators perform implicit dereferencing operations for reference types:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
type
|
||||
PNode = ref TNode
|
||||
|
|
@ -1489,12 +1489,12 @@ Procedural type
|
|||
---------------
|
||||
A procedural type is a (somewhat abstract) pointer to a procedure.
|
||||
``nil`` is an allowed value for a variable of a procedural type.
|
||||
Nimrod uses procedural types to achieve `functional`:idx: programming
|
||||
Nim uses procedural types to achieve `functional`:idx: programming
|
||||
techniques.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc echoItem(x: int) = echo(x)
|
||||
|
||||
proc forEach(action: proc (x: int)) =
|
||||
|
|
@ -1513,13 +1513,13 @@ listed in the `manual <manual.html>`_.
|
|||
|
||||
Modules
|
||||
=======
|
||||
Nimrod supports splitting a program into pieces with a module concept.
|
||||
Nim supports splitting a program into pieces with a module concept.
|
||||
Each module is in its own file. Modules enable `information hiding`:idx: and
|
||||
`separate compilation`:idx:. A module may gain access to symbols of another
|
||||
module by the `import`:idx: statement. Only top-level symbols that are marked
|
||||
with an asterisk (``*``) are exported:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# Module A
|
||||
var
|
||||
x*, y: int
|
||||
|
|
@ -1554,7 +1554,7 @@ The algorithm for compiling modules is:
|
|||
|
||||
This is best illustrated by an example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# Module A
|
||||
type
|
||||
T1* = int # Module A exports the type ``T1``
|
||||
|
|
@ -1565,7 +1565,7 @@ This is best illustrated by an example:
|
|||
|
||||
main()
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# Module B
|
||||
import A # A is not parsed here! Only the already known symbols
|
||||
# of A are imported.
|
||||
|
|
@ -1581,15 +1581,15 @@ the symbol is ambiguous, it even *has* to be qualified. A symbol is ambiguous
|
|||
if it is defined in two (or more) different modules and both modules are
|
||||
imported by a third one:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# Module A
|
||||
var x*: string
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# Module B
|
||||
var x*: int
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# Module C
|
||||
import A, B
|
||||
write(stdout, x) # error: x is ambiguous
|
||||
|
|
@ -1602,15 +1602,15 @@ imported by a third one:
|
|||
But this rule does not apply to procedures or iterators. Here the overloading
|
||||
rules apply:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# Module A
|
||||
proc x*(a: int): string = result = $a
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# Module B
|
||||
proc x*(a: string): string = result = $a
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# Module C
|
||||
import A, B
|
||||
write(stdout, x(3)) # no error: A.x is called
|
||||
|
|
@ -1627,7 +1627,7 @@ The normal ``import`` statement will bring in all exported symbols.
|
|||
These can be limited by naming symbols which should be excluded with
|
||||
the ``except`` qualifier.
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
import mymodule except y
|
||||
|
||||
|
||||
|
|
@ -1638,19 +1638,19 @@ We have already seen the simple ``import`` statement that just imports all
|
|||
exported symbols. An alternative that only imports listed symbols is the
|
||||
``from import`` statement:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
from mymodule import x, y, z
|
||||
|
||||
The ``from`` statement can also force namespace qualification on
|
||||
symbols, thereby making symbols available, but needing to be qualified
|
||||
to be used.
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
from mymodule import x, y, z
|
||||
|
||||
x() # use x without any qualification
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
from mymodule import nil
|
||||
|
||||
mymodule.x() # must qualify x with the module name as prefix
|
||||
|
|
@ -1660,7 +1660,7 @@ to be used.
|
|||
Since module names are generally long to be descriptive, you can also
|
||||
define a shorter alias to use when qualifying symbols.
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
from mymodule as m import nil
|
||||
|
||||
m.x() # m is aliasing mymodule
|
||||
|
|
@ -1672,7 +1672,7 @@ The ``include`` statement does something fundamentally different than
|
|||
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:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
include fileA, fileB, fileC
|
||||
|
||||
**Note**: The documentation generator currently does not follow ``include``
|
||||
|
|
@ -1683,7 +1683,7 @@ generated documentation.
|
|||
Part 2
|
||||
======
|
||||
|
||||
So, now that we are done with the basics, let's see what Nimrod offers apart
|
||||
So, now that we are done with the basics, let's see what Nim offers apart
|
||||
from a nice syntax for procedural programming: `Part II <tut2.html>`_
|
||||
|
||||
|
||||
|
|
|
|||
139
doc/tut2.txt
139
doc/tut2.txt
|
|
@ -1,9 +1,9 @@
|
|||
=========================
|
||||
Nimrod Tutorial (Part II)
|
||||
=========================
|
||||
======================
|
||||
Nim Tutorial (Part II)
|
||||
======================
|
||||
|
||||
:Author: Andreas Rumpf
|
||||
:Version: |nimrodversion|
|
||||
:Version: |nimversion|
|
||||
|
||||
.. contents::
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ Introduction
|
|||
only have originated in California." --Edsger Dijkstra
|
||||
|
||||
|
||||
This document is a tutorial for the advanced constructs of the *Nimrod*
|
||||
This document is a tutorial for the advanced constructs of the *Nim*
|
||||
programming language. **Note that this document is somewhat obsolete as the**
|
||||
`manual <manual.html>`_ **contains many more examples of the advanced language
|
||||
features.**
|
||||
|
|
@ -24,18 +24,18 @@ features.**
|
|||
Pragmas
|
||||
=======
|
||||
|
||||
Pragmas are Nimrod's method to give the compiler additional information/
|
||||
Pragmas are Nim's method to give the compiler additional information/
|
||||
commands without introducing a massive number of new keywords. Pragmas are
|
||||
enclosed in the special ``{.`` and ``.}`` curly dot brackets. This tutorial
|
||||
does not cover pragmas. See the `manual <manual.html#pragmas>`_ or `user guide
|
||||
<nimrodc.html#additional-features>`_ for a description of the available
|
||||
<nimc.html#additional-features>`_ for a description of the available
|
||||
pragmas.
|
||||
|
||||
|
||||
Object Oriented Programming
|
||||
===========================
|
||||
|
||||
While Nimrod's support for object oriented programming (OOP) is minimalistic,
|
||||
While Nim's support for object oriented programming (OOP) is minimalistic,
|
||||
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
|
||||
and more efficient code. In particular, prefering composition over inheritance
|
||||
|
|
@ -55,7 +55,7 @@ a *constructor*).
|
|||
Objects have access to their type at runtime. There is an
|
||||
``of`` operator that can be used to check the object's type:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
TPerson = object of TObject
|
||||
name*: string # the * means that `name` is accessible from other modules
|
||||
|
|
@ -86,20 +86,20 @@ in the GTK wrapper for instance.)
|
|||
|
||||
**Note**: Composition (*has-a* relation) is often preferable to inheritance
|
||||
(*is-a* relation) for simple code reuse. Since objects are value types in
|
||||
Nimrod, composition is as efficient as inheritance.
|
||||
Nim, composition is as efficient as inheritance.
|
||||
|
||||
|
||||
Mutually recursive types
|
||||
------------------------
|
||||
|
||||
Objects, tuples and references can model quite complex data structures which
|
||||
depend on each other; they are *mutually recursive*. In Nimrod
|
||||
depend on each other; they are *mutually recursive*. In Nim
|
||||
these types can only be declared within a single type section. (Anything else
|
||||
would require arbitrary symbol lookahead which slows down compilation.)
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
PNode = ref TNode # a traced reference to a TNode
|
||||
TNode = object
|
||||
|
|
@ -114,7 +114,7 @@ Example:
|
|||
|
||||
Type conversions
|
||||
----------------
|
||||
Nimrod distinguishes between `type casts`:idx: and `type conversions`:idx:.
|
||||
Nim distinguishes between `type casts`:idx: and `type conversions`:idx:.
|
||||
Casts are done with the ``cast`` operator and force the compiler to
|
||||
interpret a bit pattern to be of another type.
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ raised.
|
|||
The syntax for type conversions is ``destination_type(expression_to_convert)``
|
||||
(like an ordinary call):
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc getID(x: TPerson): int =
|
||||
TStudent(x).id
|
||||
|
||||
|
|
@ -141,9 +141,9 @@ variant types are needed.
|
|||
|
||||
An example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
# This is an example how an abstract syntax tree could be modeled in Nimrod
|
||||
# This is an example how an abstract syntax tree could be modeled in Nim
|
||||
type
|
||||
TNodeKind = enum # the different node types
|
||||
nkInt, # a leaf with an integer value
|
||||
|
|
@ -183,8 +183,8 @@ bound to a class. This has disadvantages:
|
|||
* Often it is unclear where the method should belong to: is
|
||||
``join`` a string method or an array method?
|
||||
|
||||
Nimrod avoids these problems by not assigning methods to a class. All methods
|
||||
in Nimrod are multi-methods. As we will see later, multi-methods are
|
||||
Nim avoids these problems by not assigning methods to a class. All methods
|
||||
in Nim are multi-methods. As we will see later, multi-methods are
|
||||
distinguished from procs only for dynamic binding purposes.
|
||||
|
||||
|
||||
|
|
@ -199,7 +199,7 @@ If there are no remaining arguments, the parentheses can be omitted:
|
|||
This method call syntax is not restricted to objects, it can be used
|
||||
for any type:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
echo("abc".len) # is the same as echo(len("abc"))
|
||||
echo("abc".toUpper())
|
||||
|
|
@ -211,7 +211,7 @@ postfix notation.)
|
|||
|
||||
So "pure object oriented" code is easy to write:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
import strutils
|
||||
|
||||
stdout.writeln("Give a list of numbers (separated by spaces): ")
|
||||
|
|
@ -221,12 +221,12 @@ So "pure object oriented" code is easy to write:
|
|||
|
||||
Properties
|
||||
----------
|
||||
As the above example shows, Nimrod has no need for *get-properties*:
|
||||
As the above example shows, Nim has no need for *get-properties*:
|
||||
Ordinary get-procedures that are called with the *method call syntax* achieve
|
||||
the same. But setting a value is different; for this a special setter syntax
|
||||
is needed:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
type
|
||||
TSocket* = object of TObject
|
||||
|
|
@ -252,7 +252,7 @@ is needed:
|
|||
The ``[]`` array access operator can be overloaded to provide
|
||||
`array properties`:idx:\ :
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
TVector* = object
|
||||
x, y, z: float
|
||||
|
|
@ -283,7 +283,7 @@ Dynamic dispatch
|
|||
Procedures always use static dispatch. For dynamic dispatch replace the
|
||||
``proc`` keyword by ``method``:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
PExpr = ref object of TObject ## abstract base class for an expression
|
||||
PLiteral = ref object of PExpr
|
||||
|
|
@ -311,7 +311,7 @@ requires dynamic binding.
|
|||
In a multi-method all parameters that have an object type are used for the
|
||||
dispatching:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
type
|
||||
TThing = object of TObject
|
||||
|
|
@ -336,7 +336,7 @@ As the example demonstrates, invocation of a multi-method cannot be ambiguous:
|
|||
Collide 2 is preferred over collide 1 because the resolution works from left to
|
||||
right. Thus ``TUnit, TThing`` is preferred over ``TThing, TUnit``.
|
||||
|
||||
**Perfomance note**: Nimrod does not produce a virtual method table, but
|
||||
**Perfomance note**: Nim does not produce a virtual method table, but
|
||||
generates dispatch trees. This avoids the expensive indirect branch for method
|
||||
calls and enables inlining. However, other optimizations like compile time
|
||||
evaluation or dead code elimination do not work with methods.
|
||||
|
|
@ -345,7 +345,7 @@ evaluation or dead code elimination do not work with methods.
|
|||
Exceptions
|
||||
==========
|
||||
|
||||
In Nimrod exceptions are objects. By convention, exception types are
|
||||
In Nim exceptions are objects. By convention, exception types are
|
||||
prefixed with an 'E', not 'T'. The `system <system.html>`_ module defines an
|
||||
exception hierarchy that you might want to stick to. Exceptions derive from
|
||||
E_Base, which provides the common interface.
|
||||
|
|
@ -364,7 +364,7 @@ Raise statement
|
|||
---------------
|
||||
Raising an exception is done with the ``raise`` statement:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
var
|
||||
e: ref EOS
|
||||
new(e)
|
||||
|
|
@ -375,7 +375,7 @@ If the ``raise`` keyword is not followed by an expression, the last exception
|
|||
is *re-raised*. For the purpose of avoiding repeating this common code pattern,
|
||||
the template ``newException`` in the ``system`` module can be used:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
raise newException(EOS, "the request to the OS failed")
|
||||
|
||||
|
||||
|
|
@ -384,7 +384,7 @@ Try statement
|
|||
|
||||
The ``try`` statement handles exceptions:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
# read the first two lines of a text file that should contain numbers
|
||||
# and tries to add them
|
||||
var
|
||||
|
|
@ -428,7 +428,7 @@ If you need to *access* the actual exception object or message inside an
|
|||
<system.html#getCurrentExceptionMsg>`_ procs from the `system <system.html>`_
|
||||
module. Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
try:
|
||||
doSomethingHere()
|
||||
except:
|
||||
|
|
@ -460,7 +460,7 @@ instance, if you specify that a proc raises ``EIO``, and at some point it (or
|
|||
one of the procs it calls) starts raising a new exception the compiler will
|
||||
prevent that proc from compiling. Usage example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc complexProc() {.raises: [EIO, EArithmetic].} =
|
||||
...
|
||||
|
||||
|
|
@ -476,21 +476,21 @@ help you locate the offending code which has changed.
|
|||
If you want to add the ``{.raises.}`` pragma to existing code, the compiler can
|
||||
also help you. You can add the ``{.effects.}`` pragma statement to your proc and
|
||||
the compiler will output all inferred effects up to that point (exception
|
||||
tracking is part of Nimrod's effect system). Another more roundabout way to
|
||||
find out the list of exceptions raised by a proc is to use the Nimrod ``doc2``
|
||||
tracking is part of Nim's effect system). Another more roundabout way to
|
||||
find out the list of exceptions raised by a proc is to use the Nim ``doc2``
|
||||
command which generates documentation for a whole module and decorates all
|
||||
procs with the list of raised exceptions. You can read more about Nimrod's
|
||||
procs with the list of raised exceptions. You can read more about Nim's
|
||||
`effect system and related pragmas in the manual <manual.html#effect-system>`_.
|
||||
|
||||
|
||||
Generics
|
||||
========
|
||||
|
||||
Generics are Nimrod's means to parametrize procs, iterators or types
|
||||
Generics are Nim's means to parametrize procs, iterators or types
|
||||
with `type parameters`:idx:. They are most useful for efficient type safe
|
||||
containers:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
TBinaryTree[T] = object # TBinaryTree is a generic type with
|
||||
# with generic param ``T``
|
||||
|
|
@ -557,7 +557,7 @@ is not hidden and is used in the ``preorder`` iterator.
|
|||
Templates
|
||||
=========
|
||||
|
||||
Templates are a simple substitution mechanism that operates on Nimrod's
|
||||
Templates are a simple substitution mechanism that operates on Nim's
|
||||
abstract syntax trees. Templates are processed in the semantic pass of the
|
||||
compiler. They integrate well with the rest of the language and share none
|
||||
of C's preprocessor macros flaws.
|
||||
|
|
@ -566,7 +566,7 @@ To *invoke* a template, call it like a procedure.
|
|||
|
||||
Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
template `!=` (a, b: expr): expr =
|
||||
# this definition exists in the System module
|
||||
not (a == b)
|
||||
|
|
@ -585,7 +585,7 @@ for IEEE floating point numbers - NaN breaks basic boolean logic.)
|
|||
Templates are especially useful for lazy evaluation purposes. Consider a
|
||||
simple proc for logging:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
const
|
||||
debug = true
|
||||
|
||||
|
|
@ -602,7 +602,7 @@ evaluation for procedures is *eager*).
|
|||
|
||||
Turning the ``log`` proc into a template solves this problem:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
const
|
||||
debug = true
|
||||
|
||||
|
|
@ -618,32 +618,11 @@ The parameters' types can be ordinary types or the meta types ``expr``
|
|||
(stands for *type description*). If the template has no explicit return type,
|
||||
``stmt`` is used for consistency with procs and methods.
|
||||
|
||||
The template body does not open a new scope. To open a new scope use a ``block``
|
||||
statement:
|
||||
|
||||
.. code-block:: nimrod
|
||||
template declareInScope(x: expr, t: typeDesc): stmt {.immediate.} =
|
||||
var x: t
|
||||
|
||||
template declareInNewScope(x: expr, t: typeDesc): stmt {.immediate.} =
|
||||
# open a new scope:
|
||||
block:
|
||||
var x: t
|
||||
|
||||
declareInScope(a, int)
|
||||
a = 42 # works, `a` is known here
|
||||
|
||||
declareInNewScope(b, int)
|
||||
b = 42 # does not work, `b` is unknown
|
||||
|
||||
(The `manual explains <manual.html#ordinary-vs-immediate-templates>`_ why the
|
||||
``immediate`` pragma is needed for these templates.)
|
||||
|
||||
If there is a ``stmt`` parameter it should be the last in the template
|
||||
declaration. The reason is that statements can be passed to a template
|
||||
via a special ``:`` syntax:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
template withFile(f: expr, filename: string, mode: TFileMode,
|
||||
body: stmt): stmt {.immediate.} =
|
||||
|
|
@ -672,18 +651,18 @@ Macros
|
|||
======
|
||||
|
||||
Macros enable advanced compile-time code transformations, but they cannot
|
||||
change Nimrod's syntax. However, this is no real restriction because Nimrod's
|
||||
syntax is flexible enough anyway. Macros have to be implemented in pure Nimrod
|
||||
change Nim's syntax. However, this is no real restriction because Nim's
|
||||
syntax is flexible enough anyway. Macros have to be implemented in pure Nim
|
||||
code if `foreign function interface (FFI)
|
||||
<manual.html#foreign-function-interface>`_ is not enabled in the compiler, but
|
||||
other than that restriction (which at some point in the future will go away)
|
||||
you can write any kind of Nimrod code and the compiler will run it at compile
|
||||
you can write any kind of Nim code and the compiler will run it at compile
|
||||
time.
|
||||
|
||||
There are two ways to write a macro, either *generating* Nimrod source code and
|
||||
There are two ways to write a macro, either *generating* Nim source code and
|
||||
letting the compiler parse it, or creating manually an abstract syntax tree
|
||||
(AST) which you feed to the compiler. In order to build the AST one needs to
|
||||
know how the Nimrod concrete syntax is converted to an abstract syntax tree
|
||||
know how the Nim concrete syntax is converted to an abstract syntax tree
|
||||
(AST). The AST is documented in the `macros <macros.html>`_ module.
|
||||
|
||||
Once your macro is finished, there are two ways to invoke it:
|
||||
|
|
@ -698,13 +677,13 @@ Expression Macros
|
|||
The following example implements a powerful ``debug`` command that accepts a
|
||||
variable number of arguments:
|
||||
|
||||
.. code-block:: nimrod
|
||||
# to work with Nimrod syntax trees, we need an API that is defined in the
|
||||
.. code-block:: nim
|
||||
# to work with Nim syntax trees, we need an API that is defined in the
|
||||
# ``macros`` module:
|
||||
import macros
|
||||
|
||||
macro debug(n: varargs[expr]): stmt =
|
||||
# `n` is a Nimrod AST that contains a list of expressions;
|
||||
# `n` is a Nim AST that contains a list of expressions;
|
||||
# this macro returns a list of statements:
|
||||
result = newNimNode(nnkStmtList, n)
|
||||
# iterate over any argument that is passed to this macro:
|
||||
|
|
@ -727,7 +706,7 @@ variable number of arguments:
|
|||
|
||||
The macro call expands to:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
write(stdout, "a[0]")
|
||||
write(stdout, ": ")
|
||||
writeln(stdout, a[0])
|
||||
|
|
@ -751,7 +730,7 @@ invoked by an expression following a colon.
|
|||
The following example outlines a macro that generates a lexical analyzer from
|
||||
regular expressions:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
macro case_token(n: stmt): stmt =
|
||||
# creates a lexical analyzer from regular expressions
|
||||
|
|
@ -784,7 +763,7 @@ To give a footstart to writing macros we will show now how to turn your typical
|
|||
dynamic code into something that compiles statically. For the exercise we will
|
||||
use the following snippet of code as the starting point:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
|
||||
import strutils, tables
|
||||
|
||||
|
|
@ -848,7 +827,7 @@ time string with the *generated source code*, which we then pass to the
|
|||
``parseStmt`` proc from the `macros module <macros.html>`_. Here is the
|
||||
modified source code implementing the macro:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
import macros, strutils
|
||||
|
||||
macro readCfgAndBuildSource(cfgFilename: string): stmt =
|
||||
|
|
@ -893,13 +872,13 @@ this limitation by using the ``slurp`` proc from the `system module
|
|||
``gorge`` which executes an external program and captures its output).
|
||||
|
||||
The interesting thing is that our macro does not return a runtime ``TTable``
|
||||
object. Instead, it builds up Nimrod source code into the ``source`` variable.
|
||||
object. Instead, it builds up Nim source code into the ``source`` variable.
|
||||
For each line of the configuration file a ``const`` variable will be generated.
|
||||
To avoid conflicts we prefix these variables with ``cfg``. In essence, what the
|
||||
compiler is doing is replacing the line calling the macro with the following
|
||||
snippet of code:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
const cfgversion= "1.1"
|
||||
const cfglicenseOwner= "Hyori Lee"
|
||||
const cfglicenseKey= "M1Tl3PjBWO2CC48m"
|
||||
|
|
@ -919,14 +898,14 @@ Generating AST by hand
|
|||
++++++++++++++++++++++
|
||||
|
||||
To generate an AST we would need to intimately know the structures used by the
|
||||
Nimrod compiler exposed in the `macros module <macros.html>`_, which at first
|
||||
Nim compiler exposed in the `macros module <macros.html>`_, which at first
|
||||
look seems a daunting task. But we can use as helper shortcut the ``dumpTree``
|
||||
macro, which is used as a statement macro instead of an expression macro.
|
||||
Since we know that we want to generate a bunch of ``const`` symbols we can
|
||||
create the following source file and compile it to see what the compiler
|
||||
*expects* from us:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
import macros
|
||||
|
||||
dumpTree:
|
||||
|
|
@ -969,7 +948,7 @@ identifier, optionally a type (can be an *empty* node) and the value. Armed
|
|||
with this knowledge, let's look at the finished version of the AST building
|
||||
macro:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
import macros, strutils
|
||||
|
||||
macro readCfgAndBuildAST(cfgFilename: string): stmt =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue