version 0.7.6

This commit is contained in:
Andreas Rumpf 2009-04-22 15:55:27 +02:00
commit e792940f52
106 changed files with 8394 additions and 10083 deletions

View file

@ -1,28 +1,25 @@
"Incorrect documentation is often worse than no documentation."
Incorrect documentation is often worse than no documentation.
-- Bertrand Meyer
The documentation consists of several documents:
- | `Nimrod tutorial (part I) <tut1.html>`_
- | `Tutorial (part I) <tut1.html>`_
| The Nimrod tutorial part one deals with the basics.
- | `Nimrod tutorial (part II) <tut2.html>`_
- | `Tutorial (part II) <tut2.html>`_
| The Nimrod tutorial part two deals with the advanced language constructs.
- | `Nimrod manual <manual.html>`_
| The Nimrod manual is a draft that will evolve into a proper specification.
- | `Library documentation <lib.html>`_
| This document describes Nimrod's standard library.
- | `User guide for the Nimrod Compiler <nimrodc.html>`_
- | `User guide <nimrodc.html>`_
| The user guide lists command line arguments, special features of the
compiler, etc.
- | `User guide for the Embedded Nimrod Debugger <endb.html>`_
| This document describes how to use the Embedded Debugger.
- | `Manual <manual.html>`_
| The Nimrod manual is a draft that will evolve into a proper specification.
- | `Nimrod library documentation <lib.html>`_
| This document describes Nimrod's standard library.
- | `Nimrod internal documentation <intern.html>`_
- | `Internal documentation <intern.html>`_
| The internal documentation describes how the compiler is implemented. Read
this if you want to hack the compiler.

View file

@ -5,7 +5,7 @@ Short description of Nimrod's modules
Module Description
============== ==========================================================
nimrod main module: parses the command line and calls
```main.MainCommand``
``main.MainCommand``
main implements the top-level command dispatching
lexbase buffer handling of the lexical analyser
scanner lexical analyser
@ -31,6 +31,7 @@ sigmatch contains the matching algorithm that is used for proc
semexprs contains the semantic checking phase for expressions
semstmts contains the semantic checking phase for statements
semtypes contains the semantic checking phase for types
seminst instantiation of generic procs and types
semfold contains code to deal with constant folding
evals contains an AST interpreter for compile time evaluation
pragmas semantic checking of pragmas

View file

@ -118,7 +118,7 @@ ifStmt ::= 'if' expr ':' stmt ('elif' expr ':' stmt)* ['else' ':' stmt]
whenStmt ::= 'when' expr ':' stmt ('elif' expr ':' stmt)* ['else' ':' stmt]
caseStmt ::= 'case' expr [':'] ('of' sliceExprList ':' stmt)*
('elif' expr ':' stmt)*
['else' ':' stmt]
['else' ':' stmt]
whileStmt ::= 'while' expr ':' stmt
forStmt ::= 'for' symbol (comma symbol)* 'in' expr ['..' expr] ':' stmt
exceptList ::= [qualifiedIdent (comma qualifiedIdent)*]

View file

@ -6,12 +6,15 @@ Nimrod Standard Library
:Version: |nimrodversion|
Though the Nimrod Standard Library is still evolving, it is already quite
usable. It is divided into basic libraries that contains modules that virtually
every program will need and advanced libraries which are more heavy weight.
Advanced libraries are in the ``lib/base`` directory.
usable. It is divided into *pure libraries*, *impure libraries* and *wrappers*.
Basic libraries
===============
Pure libraries do not depend on any external ``*.dll`` or ``lib*.so`` binary
while impure libraries do. A wrapper is an impure library that is a very
low-level interface to a C library.
Pure libraries
==============
* `system <system.html>`_
Basic procs and operators that every program needs. It also provides IO
@ -51,6 +54,12 @@ Basic libraries
literals, raw string literals and triple quote string literals are supported
as in the Nimrod programming language.
* `parsexml <parsexml.html>`_
The ``parsexml`` module implements a simple high performance XML/HTML parser.
The only encoding that is supported is UTF-8. The parser has been designed
to be somewhat error correcting, so that even some "wild HTML" found on the
web can be parsed with it.
* `strtabs <strtabs.html>`_
The ``strtabs`` module implements an efficient hash table that is a mapping
from strings to strings. Supports a case-sensitive, case-insensitive and
@ -68,17 +77,31 @@ Basic libraries
Nimrod types.
* `lexbase <lexbase.html>`_
This is a low level module that implements an extremely efficent buffering
This is a low level module that implements an extremely efficient buffering
scheme for lexers and parsers. This is used by the ``parsecfg`` module.
* `terminal <terminal.html>`_
This module contains a few procedures to control the *terminal*
(also called *console*). The implementation simply uses ANSI escape
sequences and does not depend on any other module.
Advanced libaries
=================
* `cgi <cgi.html>`_
This module implements helper procs for CGI applictions.
* `unicode <unicode.html>`_
This module provides support to handle the Unicode UTF-8 encoding.
* `regexprs <regexprs.html>`_
This module contains procedures and operators for handling regular
expressions.
* `md5 <md5.html>`_
This module implements the MD5 checksum algorithm.
Impure libraries
================
* `dialogs <dialogs.html>`_
This module implements portable dialogs for Nimrod; the implementation
builds on the GTK interface. On Windows, native dialogs are shown if
@ -86,6 +109,11 @@ Advanced libaries
* `zipfiles <zipfiles.html>`_
This module implements a zip archive creator/reader/modifier.
* `web <web.html>`_
This module contains simple high-level procedures for dealing with the
web like loading the contents of a web page from an URL.
Wrappers
========
@ -97,6 +125,12 @@ not contained in the distribution. You can then find them on the website.
Contains a wrapper for the POSIX standard.
* `windows <windows.html>`_
Contains a wrapper for the Win32 API.
* `mysql <mysql.html>`_
Contains a wrapper for the mySQL API.
* `sqlite3 <sqlite3.html>`_
Contains a wrapper for SQLite 3 API.
* `libcurl <libcurl.html>`_
Contains a wrapper for the libcurl library.
* `shellapi <shellapi.html>`_
Contains a wrapper for the ``shellapi.h`` header.
* `shfolder <shfolder.html>`_

View file

@ -1011,8 +1011,8 @@ char '\0'
bool false
ref or pointer type nil
procedural type nil
sequence nil (**not** ``@[]``)
string nil (**not** "")
sequence nil (*not* ``@[]``)
string nil (*not* "")
tuple[x: A, y: B, ...] (default(A), default(B), ...)
(analogous for objects)
array[0..., T] [default(T), ...]
@ -1080,9 +1080,9 @@ Case statement
Syntax::
caseStmt ::= 'case' expr ('of' sliceExprList ':' stmt)*
('elif' expr ':' stmt)*
['else' ':' stmt]
caseStmt ::= 'case' expr [':'] ('of' sliceExprList ':' stmt)*
('elif' expr ':' stmt)*
['else' ':' stmt]
Example:
@ -1241,11 +1241,11 @@ sugar for:
``return`` without an expression is a short notation for ``return result`` if
the proc has a return type. The `result`:idx: variable is always the return
value of the procedure. It is automatically declared by the compiler. As all
variables, ``result`` is initialized to (binary) zero::
variables, ``result`` is initialized to (binary) zero:
.. code-block:: nimrod
proc returnZero(): int =
# implicitely returns 0
proc returnZero(): int =
# implicitely returns 0
Yield statement
@ -1649,7 +1649,7 @@ possible within a single ``type`` section.
Generics
~~~~~~~~
`Version 0.7.4: Complex generic types like in the example do not work.`:red:
`Version 0.7.6: Generic types like in the example do not work.`:red:
Example:

View file

@ -208,8 +208,9 @@ Acyclic Pragma
~~~~~~~~~~~~~~
The `acyclic`:idx: pragma can be used for object types to mark them as acyclic
even though they seem to be cyclic. This is an **optimization** for the garbage
collector to not consider objects of this type as part of a cycle::
collector to not consider objects of this type as part of a cycle:
.. code-block:: nimrod
type
PNode = ref TNode
TNode {.acyclic, final.} = object

File diff suppressed because it is too large Load diff

View file

@ -46,12 +46,14 @@ The most used commands and switches have abbreviations, so you can also use::
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. String literals
are enclosed in double quotes. The ``var`` statement declares a new variable
named ``name`` of type ``string`` with the value that is returned by the
``readline`` procedure. Since the compiler knows that ``readline`` returns
a string, you can leave out the type in the declaration (this is called
`local type inference`:idx:). So this will work too:
starts. Indentation is Nimrod'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
a new variable named ``name`` of type ``string`` with the value that is
returned by the ``readline`` procedure. Since the compiler knows that
``readline`` 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
var name = readline(stdin)
@ -73,7 +75,7 @@ keywords, comments, operators, and other punctation marks. Case is
*insignificant* in Nimrod and even underscores are ignored:
``This_is_an_identifier`` and this is the same identifier
``ThisIsAnIdentifier``. This feature enables you to use other
peoples 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
(was it ``parseURL`` or ``parseUrl`` or ``parse_URL``?).
@ -129,6 +131,9 @@ the syntax, watch their indentation:
Echo("Hi!")
# comment has not the right indentation -> syntax error!
**Note**: To comment out a large piece of code, it is often better to use a
``when false:`` statement.
Numbers
-------
@ -137,7 +142,7 @@ Numerical literals are written as in most other languages. As a special twist,
underscores are allowed for better readability: ``1_000_000`` (one million).
A number that contains a dot (or 'e' or 'E') is a floating point literal:
``1.0e9`` (one million). Hexadecimal literals are prefixed with ``0x``,
binary literals with ``0b`` and octal literals with ``0c``. A leading zero
binary literals with ``0b`` and octal literals with ``0o``. A leading zero
alone does not produce an octal.
@ -426,7 +431,11 @@ The ``when`` statement is useful for writing platform specific code, similar to
the ``#ifdef`` construct in the C programming language.
**Note**: The documentation generator currently always follows the first branch
of when statements.
of when statements.
**Note**: To comment out a large piece of code, it is often better to use a
``when false:`` statement than to use real comments. This way nesting is
possible.
Statements and indentation
@ -440,7 +449,7 @@ 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 intended, but single simple statements do not:
to be indented, but single simple statements do not:
.. code-block:: nimrod
# no indentation needed for single assignment statement:
@ -518,9 +527,11 @@ shorthand for ``return result``. So all tree code snippets are equivalent:
.. code-block:: nimrod
return 42
.. code-block:: nimrod
result = 42
return
.. code-block:: nimrod
result = 42
return result
@ -880,7 +891,7 @@ In Nimrod new types can be defined within a ``type`` statement:
.. code-block:: nimrod
type
biggestInt = int64 # biggest integer type that is available
biggestFLoat = float64 # biggest float type that is available
biggestFloat = float64 # biggest float type that is available
Enumeration and object types cannot be defined on the fly, but only within a
``type`` statement.
@ -980,7 +991,7 @@ basetype can only be an ordinal type. The reason is that sets are implemented
as high performance bit vectors.
Sets can be constructed via the set constructor: ``{}`` is the empty set. The
empty set is type combatible with any concrete set type. The constructor
empty set is type compatible with any concrete set type. The constructor
can also be used to include elements (and ranges of elements):
.. code-block:: nimrod
@ -1013,7 +1024,7 @@ operation meaning
================== ========================================================
Sets are often used to define a type for the *flags* of a procedure. This is
much cleaner (and type safe solution) solution than just defining integer
much cleaner (and type safe) solution than just defining integer
constants that should be ``or``'ed together.
@ -1047,36 +1058,6 @@ The built-in ``len`` proc returns the array's length. ``low(a)`` returns the
lowest valid index for the array `a` and ``high(a)`` the highest valid index.
Open arrays
-----------
Often fixed size arrays turn out to be too inflexible; procedures should
be able to deal with arrays of different sizes. The `openarray`:idx: type
allows this. Openarrays are always indexed with an ``int`` starting at
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
an openarray parameter, the index type does not matter.
The openarray type cannot be nested: Multidimensional openarrays are not
supported because this is seldom needed and cannot be done efficiently.
An openarray is 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
proc myWriteln(f: TFile, a: openarray[string]) =
for s in items(a):
write(f, s)
write(f, "\n")
myWriteln(stdout, "abc", "def", "xyz")
# is transformed by the compiler to:
myWriteln(stdout, ["abc", "def", "xyz"])
This transformation is only done if the openarray parameter is the
last parameter in the procedure header.
Sequences
---------
`Sequences`:idx: are similar to arrays but of dynamic length which may change
@ -1108,6 +1089,38 @@ rather than ``nil`` as the *empty* value. But ``@[]`` creates a sequence
object on the heap, so there is a trade-off to be made here.
Open arrays
-----------
**Note**: Openarrays can only be used for parameters.
Often fixed size arrays turn out to be too inflexible; procedures should
be able to deal with arrays of different sizes. The `openarray`:idx: type
allows this. Openarrays are always indexed with an ``int`` starting at
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
an openarray parameter, the index type does not matter.
The openarray type cannot be nested: Multidimensional openarrays are not
supported because this is seldom needed and cannot be done efficiently.
An openarray is 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
proc myWriteln(f: TFile, a: openarray[string]) =
for s in items(a):
write(f, s)
write(f, "\n")
myWriteln(stdout, "abc", "def", "xyz")
# is transformed by the compiler to:
myWriteln(stdout, ["abc", "def", "xyz"])
This transformation is only done if the openarray parameter is the
last parameter in the procedure header.
Tuples
------
@ -1271,8 +1284,19 @@ with an asterisk (``*``) are exported:
# multiply two int sequences:
for i in 0..len(a)-1: result[i] = a[i] * b[i]
when isMainModule:
# test the new ``*`` operator for sequences:
assert(@[1, 2, 3] * @[1, 2, 3] == @[1, 4, 9])
The above module exports ``x`` and ``*``, but not ``y``.
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.
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
the module as shown by the above example.
Modules that depend on each other are possible, but strongly discouraged,
because then one module cannot be reused without the other.

View file

@ -33,7 +33,8 @@ Object Oriented Programming
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
program, not *the only* way. Often a procedural approach leads to simpler
and more efficient code.
and more efficient code. In particular, prefering aggregation over inheritance
often yields to a better design.
Objects
@ -196,8 +197,8 @@ for any type:
stdout.writeln("Hallo") # the same as write(stdout, "Hallo")
If it gives you warm fuzzy feelings, you can even write ``1.`+`(2)`` instead of
``1 + 2`` and claim that Nimrod is a pure object oriented language. (That
would not even be lying: *pure OO* has no meaning anyway. :-)
``1 + 2`` and claim that Nimrod is a pure object oriented language. (But
that's not true. :-)
Properties
@ -237,15 +238,15 @@ The ``[]`` array access operator can be overloaded to provide
type
TVector* = object
x, y, z: float
proc `[]=`* (v: var TVector, i: int, value: float) =
# setter
# setter
case i
of 0: v.x = value
of 1: v.y = value
of 2: v.z = value
else: assert(false)
proc `[]`* (v: TVector, i: int): float =
# getter
case i
@ -253,25 +254,29 @@ The ``[]`` array access operator can be overloaded to provide
of 1: result = v.y
of 2: result = v.z
else: assert(false)
The example is silly, since a vector is better modelled by a tuple which
already provides ``v[]`` access.
Dynamic binding
---------------
In Nimrod procedural types are used to implement dynamic binding. The following
example also shows some more conventions: The ``self`` or ``this`` object
is named ``my`` (because it is shorter than the alternatives), each class
provides a constructor, etc.
Dynamic dispatch
----------------
In Nimrod procedural types are used to implement dynamic dispatch. The
following example also shows some more conventions: The ``self`` or ``this``
object is named ``my`` (because it is shorter than the alternatives), each
class provides a constructor, etc.
.. code-block:: nimrod
type
TFigure = object of TObject # abstract base class:
draw: proc (my: var TFigure) # concrete classes implement this proc
TFigure = object of TObject # abstract base class:
fDraw: proc (my: var TFigure) # concrete classes implement this proc
proc init(f: var TFigure) =
f.draw = nil
f.fDraw = nil
proc draw(f: var TFigure) =
# ``draw`` dispatches dynamically:
f.fDraw(f)
type
TCircle = object of TFigure
@ -282,7 +287,7 @@ provides a constructor, etc.
proc init(my: var TCircle) =
init(TFigure(my)) # call base constructor
my.radius = 5
my.draw = drawCircle
my.fdraw = drawCircle
type
TRectangle = object of TFigure
@ -294,50 +299,7 @@ provides a constructor, etc.
init(TFigure(my)) # call base constructor
my.width = 5
my.height = 10
my.draw = drawRectangle
# now use these classes:
var
r: TRectangle
c: TCircle
init(r)
init(c)
r.draw(r)
c.draw(c)
The last line shows the syntactical difference between static and dynamic
binding: The ``r.draw(r)`` dynamic call refers to ``r`` twice. This difference
is not necessarily bad. But if you want to eliminate the somewhat redundant
``r``, it can be done by using *closures*:
.. code-block:: nimrod
type
TFigure = object of TObject # abstract base class:
draw: proc () {.closure.} # concrete classes implement this proc
proc init(f: var TFigure) =
f.draw = nil
type
TCircle = object of TFigure
radius: int
proc init(me: var TCircle) =
init(TFigure(me)) # call base constructor
me.radius = 5
me.draw = lambda () =
echo("o " & $me.radius)
type
TRectangle = object of TFigure
width, height: int
proc init(me: var TRectangle) =
init(TFigure(me)) # call base constructor
me.width = 5
me.height = 10
me.draw = lambda () =
echo("[]")
my.fdraw = drawRectangle
# now use these classes:
var
@ -348,10 +310,12 @@ is not necessarily bad. But if you want to eliminate the somewhat redundant
r.draw()
c.draw()
The example also introduces `lambda`:idx: expressions: A ``lambda`` expression
defines a new proc with the ``closure`` calling convention on the fly.
The code uses a ``draw`` procedure that is bound statically, but inside it
the dynamic dispatch happens with the help of the ``fdraw`` field. This is
slightly more inconvienent than in traditional OOP-languages, but has the
advantage of being much more flexible (and somewhat faster). The above approach
also allows some form *monkey patching* by modifying the ``fdraw`` field.
`Version 0.7.4: Closures and lambda expressions are not implemented.`:red:
Exceptions
@ -432,7 +396,7 @@ is not executed (if an exception occurs).
Generics
========
`Version 0.7.4: Complex generic types like in the example do not work.`:red:
`Version 0.7.6: Complex generic types like in the example do not work.`:red:
`Generics`:idx: are Nimrod's means to parametrize procs, iterators or types
with `type parameters`:idx:. They are most useful for efficient type safe
@ -458,8 +422,8 @@ containers:
else:
var it = root
while it != nil:
# compare the data items; uses the generic ``cmd`` proc that works for
# any type that has a ``==`` and ``<`` operator
# compare the data items; uses the generic ``cmd`` proc
# that works for any type that has a ``==`` and ``<`` operator
var c = cmp(it.data, n.data)
if c < 0:
if it.le == nil:
@ -491,7 +455,7 @@ containers:
var
root: PBinaryTree[string] # instantiate a PBinaryTree with ``string``
add(root, newNode("hallo")) # instantiates generic procs ``newNode`` and ``add``
add(root, newNode("hallo")) # instantiates ``newNode`` and ``add``
add(root, "world") # instantiates the second ``add`` proc
for str in preorder(root):
stdout.writeln(str)
@ -567,6 +531,7 @@ Turning the ``log`` proc into a template solves this problem in an elegant way:
The "types" of templates can be the symbols ``expr`` (stands for *expression*),
``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type
description*). These are no real types, they just help the compiler parsing.
In later versions, real types will be supported too.
The template body does not open a new scope. To open a new scope
use a ``block`` statement:
@ -587,6 +552,35 @@ use a ``block`` statement:
b = 42 # does not work, `b` is unknown
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
template withFile(f, filename, mode: expr, actions: stmt): stmt =
block:
var fn = filename
var f: TFile
if openFile(f, fn, mode):
try:
actions
finally:
closeFile(f)
else:
quit("cannot open: " & fn)
withFile(txt, "ttempl3.txt", fmWrite):
txt.writeln("line 1")
txt.writeln("line 2")
In the example the two ``writeln`` statements are bound to the ``actions``
parameter. The ``withFile`` template contains boilerplate code and helps to
avoid a common bug: To forget to close the file. Note how the
``var fn = filename`` statement ensures that ``filename`` is evaluated only
once.
Macros
======
@ -658,36 +652,6 @@ The macro call expands to:
writeln(stdout, x)
Lets return to the dynamic binding ``r.draw(r)`` notational "problem". Apart
from closures, there is another "solution": Define an infix ``!`` macro
operator which hides it:
.. code-block::
macro `!` (n: expr): expr =
result = newNimNode(nnkCall, n)
var dot = newNimNode(nnkDotExpr, n)
dot.add(n[1]) # obj
if n[2].kind == nnkCall:
# transforms ``obj!method(arg1, arg2, ...)`` to
# ``(obj.method)(obj, arg1, arg2, ...)``
dot.add(n[2][0]) # method
result.add(dot)
result.add(n[1]) # obj
for i in 1..n[2].len-1:
result.add(n[2][i])
else:
# transforms ``obj!method`` to
# ``(obj.method)(obj)``
dot.add(n[2]) # method
result.add(dot)
result.add(n[1]) # obj
r!draw(a, b, c) # will be transfomed into ``r.draw(r, a, b, c)``
Great! 20 lines of complex code to safe a few keystrokes! Obviously, this is
exactly you should not do! (But it makes a cool example.)
Statement Macros
----------------