doc: Trim .txt files trailing whitespace
via OSX: find . -name '*.txt' -exec sed -i '' -E 's/[[:space:]]+$//' {} +
This commit is contained in:
parent
51488766e7
commit
0b44d812f1
33 changed files with 566 additions and 566 deletions
|
|
@ -20,7 +20,7 @@ English word To use Notes
|
||||||
------------------- ------------ --------------------------------------
|
------------------- ------------ --------------------------------------
|
||||||
initialize initT ``init`` is used to create a
|
initialize initT ``init`` is used to create a
|
||||||
value type ``T``
|
value type ``T``
|
||||||
new newP ``new`` is used to create a
|
new newP ``new`` is used to create a
|
||||||
reference type ``P``
|
reference type ``P``
|
||||||
find find should return the position where
|
find find should return the position where
|
||||||
something was found; for a bool result
|
something was found; for a bool result
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ The documentation consists of several documents:
|
||||||
builtin templating system.
|
builtin templating system.
|
||||||
|
|
||||||
- | `Term rewriting macros <trmacros.html>`_
|
- | `Term rewriting macros <trmacros.html>`_
|
||||||
| Term rewriting macros enhance the compilation process with user defined
|
| Term rewriting macros enhance the compilation process with user defined
|
||||||
optimizations.
|
optimizations.
|
||||||
|
|
||||||
- | `Internal documentation <intern.html>`_
|
- | `Internal documentation <intern.html>`_
|
||||||
|
|
|
||||||
402
doc/endb.txt
402
doc/endb.txt
|
|
@ -1,203 +1,203 @@
|
||||||
==============================================
|
==============================================
|
||||||
Embedded Nim Debugger (ENDB) User Guide
|
Embedded Nim Debugger (ENDB) User Guide
|
||||||
==============================================
|
==============================================
|
||||||
|
|
||||||
:Author: Andreas Rumpf
|
:Author: Andreas Rumpf
|
||||||
:Version: |nimversion|
|
:Version: |nimversion|
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
|
|
||||||
**WARNING**: ENDB is not maintained anymore! Please help if you're interested
|
**WARNING**: ENDB is not maintained anymore! Please help if you're interested
|
||||||
in this tool.
|
in this tool.
|
||||||
|
|
||||||
Nim comes with a platform independent debugger -
|
Nim comes with a platform independent debugger -
|
||||||
the Embedded Nim Debugger (ENDB). The debugger is
|
the Embedded Nim Debugger (ENDB). The debugger is
|
||||||
*embedded* into your executable if it has been
|
*embedded* into your executable if it has been
|
||||||
compiled with the ``--debugger:on`` command line option.
|
compiled with the ``--debugger:on`` command line option.
|
||||||
This also defines the conditional symbol ``ENDB`` for you.
|
This also defines the conditional symbol ``ENDB`` for you.
|
||||||
|
|
||||||
Note: You must not compile your program with the ``--app:gui``
|
Note: You must not compile your program with the ``--app:gui``
|
||||||
command line option because then there would be no console
|
command line option because then there would be no console
|
||||||
available for the debugger.
|
available for the debugger.
|
||||||
|
|
||||||
If you start your program the debugger will immediately show
|
If you start your program the debugger will immediately show
|
||||||
a prompt on the console. You can now enter a command. The next sections
|
a prompt on the console. You can now enter a command. The next sections
|
||||||
deal with the possible commands. As usual in Nim in all commands
|
deal with the possible commands. As usual in Nim in all commands
|
||||||
underscores and case do not matter. Optional components of a command
|
underscores and case do not matter. Optional components of a command
|
||||||
are listed in brackets ``[...]`` here.
|
are listed in brackets ``[...]`` here.
|
||||||
|
|
||||||
|
|
||||||
General Commands
|
General Commands
|
||||||
================
|
================
|
||||||
|
|
||||||
``h``, ``help``
|
``h``, ``help``
|
||||||
Display a quick reference of the possible commands.
|
Display a quick reference of the possible commands.
|
||||||
|
|
||||||
``q``, ``quit``
|
``q``, ``quit``
|
||||||
Quit the debugger and the program.
|
Quit the debugger and the program.
|
||||||
|
|
||||||
<ENTER>
|
<ENTER>
|
||||||
(Without any typed command) repeat the previous debugger command.
|
(Without any typed command) repeat the previous debugger command.
|
||||||
If there is no previous command, ``step_into`` is assumed.
|
If there is no previous command, ``step_into`` is assumed.
|
||||||
|
|
||||||
Executing Commands
|
Executing Commands
|
||||||
==================
|
==================
|
||||||
|
|
||||||
``s``, ``step_into``
|
``s``, ``step_into``
|
||||||
Single step, stepping into routine calls.
|
Single step, stepping into routine calls.
|
||||||
|
|
||||||
``n``, ``step_over``
|
``n``, ``step_over``
|
||||||
Single step, without stepping into routine calls.
|
Single step, without stepping into routine calls.
|
||||||
|
|
||||||
``f``, ``skip_current``
|
``f``, ``skip_current``
|
||||||
Continue execution until the current routine finishes.
|
Continue execution until the current routine finishes.
|
||||||
|
|
||||||
``c``, ``continue``
|
``c``, ``continue``
|
||||||
Continue execution until the next breakpoint.
|
Continue execution until the next breakpoint.
|
||||||
|
|
||||||
``i``, ``ignore``
|
``i``, ``ignore``
|
||||||
Continue execution, ignore all breakpoints. This effectively quits
|
Continue execution, ignore all breakpoints. This effectively quits
|
||||||
the debugger and runs the program until it finishes.
|
the debugger and runs the program until it finishes.
|
||||||
|
|
||||||
|
|
||||||
Breakpoint Commands
|
Breakpoint Commands
|
||||||
===================
|
===================
|
||||||
|
|
||||||
``b``, ``setbreak`` [fromline [toline]] [file]
|
``b``, ``setbreak`` [fromline [toline]] [file]
|
||||||
Set a new breakpoint for the given file
|
Set a new breakpoint for the given file
|
||||||
and line numbers. If no file is given, the current execution point's
|
and line numbers. If no file is given, the current execution point's
|
||||||
filename is used. If the filename has no extension, ``.nim`` is
|
filename is used. If the filename has no extension, ``.nim`` is
|
||||||
appended for your convenience.
|
appended for your convenience.
|
||||||
If no line numbers are given, the current execution point's
|
If no line numbers are given, the current execution point's
|
||||||
line is used. If both ``fromline`` and ``toline`` are given the
|
line is used. If both ``fromline`` and ``toline`` are given the
|
||||||
breakpoint contains a line number range. Some examples if it is still
|
breakpoint contains a line number range. Some examples if it is still
|
||||||
unclear:
|
unclear:
|
||||||
|
|
||||||
* ``b 12 15 thallo`` creates a breakpoint that
|
* ``b 12 15 thallo`` creates a breakpoint that
|
||||||
will be triggered if the instruction pointer reaches one of the
|
will be triggered if the instruction pointer reaches one of the
|
||||||
lines 12-15 in the file ``thallo.nim``.
|
lines 12-15 in the file ``thallo.nim``.
|
||||||
* ``b 12 thallo`` creates a breakpoint that
|
* ``b 12 thallo`` creates a breakpoint that
|
||||||
will be triggered if the instruction pointer reaches the
|
will be triggered if the instruction pointer reaches the
|
||||||
line 12 in the file ``thallo.nim``.
|
line 12 in the file ``thallo.nim``.
|
||||||
* ``b 12`` creates a breakpoint that
|
* ``b 12`` creates a breakpoint that
|
||||||
will be triggered if the instruction pointer reaches the
|
will be triggered if the instruction pointer reaches the
|
||||||
line 12 in the current file.
|
line 12 in the current file.
|
||||||
* ``b`` creates a breakpoint that
|
* ``b`` creates a breakpoint that
|
||||||
will be triggered if the instruction pointer reaches the
|
will be triggered if the instruction pointer reaches the
|
||||||
current line in the current file again.
|
current line in the current file again.
|
||||||
|
|
||||||
``breakpoints``
|
``breakpoints``
|
||||||
Display the entire breakpoint list.
|
Display the entire breakpoint list.
|
||||||
|
|
||||||
``disable`` <identifier>
|
``disable`` <identifier>
|
||||||
Disable a breakpoint. It remains disabled until you turn it on again
|
Disable a breakpoint. It remains disabled until you turn it on again
|
||||||
with the ``enable`` command.
|
with the ``enable`` command.
|
||||||
|
|
||||||
``enable`` <identifier>
|
``enable`` <identifier>
|
||||||
Enable a breakpoint.
|
Enable a breakpoint.
|
||||||
|
|
||||||
Often it happens when debugging that you keep retyping the breakpoints again
|
Often it happens when debugging that you keep retyping the breakpoints again
|
||||||
and again because they are lost when you restart your program. This is not
|
and again because they are lost when you restart your program. This is not
|
||||||
necessary: A special pragma has been defined for this:
|
necessary: A special pragma has been defined for this:
|
||||||
|
|
||||||
|
|
||||||
The ``breakpoint`` pragma
|
The ``breakpoint`` pragma
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
The ``breakpoint`` pragma is syntactically a statement. It can be used
|
The ``breakpoint`` pragma is syntactically a statement. It can be used
|
||||||
to mark the *following line* as a breakpoint:
|
to mark the *following line* as a breakpoint:
|
||||||
|
|
||||||
.. code-block:: Nim
|
.. code-block:: Nim
|
||||||
write("1")
|
write("1")
|
||||||
{.breakpoint: "before_write_2".}
|
{.breakpoint: "before_write_2".}
|
||||||
write("2")
|
write("2")
|
||||||
|
|
||||||
The name of the breakpoint here is ``before_write_2``. Of course the
|
The name of the breakpoint here is ``before_write_2``. Of course the
|
||||||
breakpoint's name is optional - the compiler will generate one for you
|
breakpoint's name is optional - the compiler will generate one for you
|
||||||
if you leave it out.
|
if you leave it out.
|
||||||
|
|
||||||
Code for the ``breakpoint`` pragma is only generated if the debugger
|
Code for the ``breakpoint`` pragma is only generated if the debugger
|
||||||
is turned on, so you don't need to remove it from your source code after
|
is turned on, so you don't need to remove it from your source code after
|
||||||
debugging.
|
debugging.
|
||||||
|
|
||||||
|
|
||||||
The ``watchpoint`` pragma
|
The ``watchpoint`` pragma
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
The ``watchpoint`` pragma is syntactically a statement. It can be used
|
The ``watchpoint`` pragma is syntactically a statement. It can be used
|
||||||
to mark a location as a watchpoint:
|
to mark a location as a watchpoint:
|
||||||
|
|
||||||
.. code-block:: Nim
|
.. code-block:: Nim
|
||||||
var a: array [0..20, int]
|
var a: array [0..20, int]
|
||||||
|
|
||||||
{.watchpoint: a[3].}
|
{.watchpoint: a[3].}
|
||||||
for i in 0 .. 20: a[i] = i
|
for i in 0 .. 20: a[i] = i
|
||||||
|
|
||||||
ENDB then writes a stack trace whenever the content of the location ``a[3]``
|
ENDB then writes a stack trace whenever the content of the location ``a[3]``
|
||||||
changes. The current implementation only tracks a hash value of the location's
|
changes. The current implementation only tracks a hash value of the location's
|
||||||
contents and so locations that are not word sized may encounter false
|
contents and so locations that are not word sized may encounter false
|
||||||
negatives in very rare cases.
|
negatives in very rare cases.
|
||||||
|
|
||||||
Code for the ``watchpoint`` pragma is only generated if the debugger
|
Code for the ``watchpoint`` pragma is only generated if the debugger
|
||||||
is turned on, so you don't need to remove it from your source code after
|
is turned on, so you don't need to remove it from your source code after
|
||||||
debugging.
|
debugging.
|
||||||
|
|
||||||
Due to the primitive implementation watchpoints are even slower than
|
Due to the primitive implementation watchpoints are even slower than
|
||||||
breakpoints: After *every* executed Nim code line it is checked whether the
|
breakpoints: After *every* executed Nim code line it is checked whether the
|
||||||
location changed.
|
location changed.
|
||||||
|
|
||||||
|
|
||||||
Data Display Commands
|
Data Display Commands
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
``e``, ``eval`` <exp>
|
``e``, ``eval`` <exp>
|
||||||
Evaluate the expression <exp>. Note that ENDB has no full-blown expression
|
Evaluate the expression <exp>. Note that ENDB has no full-blown expression
|
||||||
evaluator built-in. So expressions are limited:
|
evaluator built-in. So expressions are limited:
|
||||||
|
|
||||||
* To display global variables prefix their names with their
|
* To display global variables prefix their names with their
|
||||||
owning module: ``nim1.globalVar``
|
owning module: ``nim1.globalVar``
|
||||||
* To display local variables or parameters just type in
|
* To display local variables or parameters just type in
|
||||||
their name: ``localVar``. If you want to inspect variables that are not
|
their name: ``localVar``. If you want to inspect variables that are not
|
||||||
in the current stack frame, use the ``up`` or ``down`` command.
|
in the current stack frame, use the ``up`` or ``down`` command.
|
||||||
|
|
||||||
Unfortunately, only inspecting variables is possible at the moment. Maybe
|
Unfortunately, only inspecting variables is possible at the moment. Maybe
|
||||||
a future version will implement a full-blown Nim expression evaluator,
|
a future version will implement a full-blown Nim expression evaluator,
|
||||||
but this is not easy to do and would bloat the debugger's code.
|
but this is not easy to do and would bloat the debugger's code.
|
||||||
|
|
||||||
Since displaying the whole data structures is often not needed and
|
Since displaying the whole data structures is often not needed and
|
||||||
painfully slow, the debugger uses a *maximal display depth* concept for
|
painfully slow, the debugger uses a *maximal display depth* concept for
|
||||||
displaying.
|
displaying.
|
||||||
|
|
||||||
You can alter the maximal display depth with the ``maxdisplay``
|
You can alter the maximal display depth with the ``maxdisplay``
|
||||||
command.
|
command.
|
||||||
|
|
||||||
``maxdisplay`` <natural>
|
``maxdisplay`` <natural>
|
||||||
Sets the maximal display depth to the given integer value. A value of 0
|
Sets the maximal display depth to the given integer value. A value of 0
|
||||||
means there is no maximal display depth. Default is 3.
|
means there is no maximal display depth. Default is 3.
|
||||||
|
|
||||||
``o``, ``out`` <filename> <exp>
|
``o``, ``out`` <filename> <exp>
|
||||||
Evaluate the expression <exp> and store its string representation into a
|
Evaluate the expression <exp> and store its string representation into a
|
||||||
file named <filename>. If the file does not exist, it will be created,
|
file named <filename>. If the file does not exist, it will be created,
|
||||||
otherwise it will be opened for appending.
|
otherwise it will be opened for appending.
|
||||||
|
|
||||||
``w``, ``where``
|
``w``, ``where``
|
||||||
Display the current execution point.
|
Display the current execution point.
|
||||||
|
|
||||||
``u``, ``up``
|
``u``, ``up``
|
||||||
Go up in the call stack.
|
Go up in the call stack.
|
||||||
|
|
||||||
``d``, ``down``
|
``d``, ``down``
|
||||||
Go down in the call stack.
|
Go down in the call stack.
|
||||||
|
|
||||||
``stackframe`` [file]
|
``stackframe`` [file]
|
||||||
Displays the content of the current stack frame in ``stdout`` or
|
Displays the content of the current stack frame in ``stdout`` or
|
||||||
appends it to the file, depending on whether a file is given.
|
appends it to the file, depending on whether a file is given.
|
||||||
|
|
||||||
``callstack``
|
``callstack``
|
||||||
Display the entire call stack (but not its content).
|
Display the entire call stack (but not its content).
|
||||||
|
|
||||||
``l``, ``locals``
|
``l``, ``locals``
|
||||||
Display the available local variables in the current stack frame.
|
Display the available local variables in the current stack frame.
|
||||||
|
|
||||||
``g``, ``globals``
|
``g``, ``globals``
|
||||||
Display all the global variables that are available for inspection.
|
Display all the global variables that are available for inspection.
|
||||||
|
|
|
||||||
46
doc/estp.txt
46
doc/estp.txt
|
|
@ -1,30 +1,30 @@
|
||||||
===================================================
|
===================================================
|
||||||
Embedded Stack Trace Profiler (ESTP) User Guide
|
Embedded Stack Trace Profiler (ESTP) User Guide
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
:Author: Andreas Rumpf
|
|
||||||
:Version: |nimversion|
|
|
||||||
|
|
||||||
|
|
||||||
Nim comes with a platform independent profiler -
|
|
||||||
the Embedded Stack Trace Profiler (ESTP). The profiler
|
|
||||||
is *embedded* into your executable. To activate the profiler you need to do:
|
|
||||||
|
|
||||||
* compile your program with the ``--profiler:on --stackTrace:on`` command
|
:Author: Andreas Rumpf
|
||||||
|
:Version: |nimversion|
|
||||||
|
|
||||||
|
|
||||||
|
Nim comes with a platform independent profiler -
|
||||||
|
the Embedded Stack Trace Profiler (ESTP). The profiler
|
||||||
|
is *embedded* into your executable. To activate the profiler you need to do:
|
||||||
|
|
||||||
|
* compile your program with the ``--profiler:on --stackTrace:on`` command
|
||||||
line options
|
line options
|
||||||
* import the ``nimprof`` module
|
* import the ``nimprof`` module
|
||||||
* run your program as usual.
|
* run your program as usual.
|
||||||
|
|
||||||
You can in fact look at ``nimprof``'s source code to see how to implement
|
You can in fact look at ``nimprof``'s source code to see how to implement
|
||||||
your own profiler.
|
your own profiler.
|
||||||
|
|
||||||
The setting ``--profiler:on`` defines the conditional symbol ``profiler``.
|
The setting ``--profiler:on`` defines the conditional symbol ``profiler``.
|
||||||
|
|
||||||
After your program has finished the profiler will create a
|
After your program has finished the profiler will create a
|
||||||
file ``profile_results.txt`` containing the profiling results.
|
file ``profile_results.txt`` containing the profiling results.
|
||||||
|
|
||||||
Since the profiler works by examining stack traces, it's essential that
|
Since the profiler works by examining stack traces, it's essential that
|
||||||
the option ``--stackTrace:on`` is active! Unfortunately this means that a
|
the option ``--stackTrace:on`` is active! Unfortunately this means that a
|
||||||
profiling build is much slower than a release build.
|
profiling build is much slower than a release build.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ Memory profiler
|
||||||
===============
|
===============
|
||||||
|
|
||||||
You can also use ESTP as a memory profiler to see which stack traces allocate
|
You can also use ESTP as a memory profiler to see which stack traces allocate
|
||||||
the most memory and thus create the most GC pressure. It may also help to
|
the most memory and thus create the most GC pressure. It may also help to
|
||||||
find memory leaks. To activate the memory profiler you need to do:
|
find memory leaks. To activate the memory profiler you need to do:
|
||||||
|
|
||||||
* compile your program with the ``--profiler:off --stackTrace:on -d:memProfiler``
|
* compile your program with the ``--profiler:off --stackTrace:on -d:memProfiler``
|
||||||
|
|
@ -40,22 +40,22 @@ find memory leaks. To activate the memory profiler you need to do:
|
||||||
* import the ``nimprof`` module
|
* import the ``nimprof`` module
|
||||||
* run your program as usual.
|
* run your program as usual.
|
||||||
|
|
||||||
Define the symbol ``ignoreAllocationSize`` so that only the number of
|
Define the symbol ``ignoreAllocationSize`` so that only the number of
|
||||||
allocations is counted and the sizes of the memory allocations do not matter.
|
allocations is counted and the sizes of the memory allocations do not matter.
|
||||||
|
|
||||||
|
|
||||||
Example results file
|
Example results file
|
||||||
====================
|
====================
|
||||||
|
|
||||||
The results file lists stack traces ordered by significance.
|
The results file lists stack traces ordered by significance.
|
||||||
|
|
||||||
The following example file has been generated by profiling the Nim compiler
|
The following example file has been generated by profiling the Nim compiler
|
||||||
itself: It shows that in total 5.4% of the runtime has been spent
|
itself: It shows that in total 5.4% of the runtime has been spent
|
||||||
in ``crcFromRope`` or its children.
|
in ``crcFromRope`` or its children.
|
||||||
|
|
||||||
In general the stack traces show you immediately where the problem is because
|
In general the stack traces show you immediately where the problem is because
|
||||||
the trace acts like an explanation; in traditional profilers you can only find
|
the trace acts like an explanation; in traditional profilers you can only find
|
||||||
expensive leaf functions easily but the *reason* why they are invoked
|
expensive leaf functions easily but the *reason* why they are invoked
|
||||||
often remains mysterious.
|
often remains mysterious.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ Source Code Filters
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
|
|
||||||
A `Source Code Filter` transforms the input character stream to an in-memory
|
A `Source Code Filter` transforms the input character stream to an in-memory
|
||||||
output stream before parsing. A filter can be used to provide templating
|
output stream before parsing. A filter can be used to provide templating
|
||||||
systems or preprocessors.
|
systems or preprocessors.
|
||||||
|
|
||||||
To use a filter for a source file the *shebang* notation is used::
|
To use a filter for a source file the *shebang* notation is used::
|
||||||
|
|
@ -52,7 +52,7 @@ Parameters and their defaults:
|
||||||
|
|
||||||
``sub: string = ""``
|
``sub: string = ""``
|
||||||
the substring that is searched for
|
the substring that is searched for
|
||||||
|
|
||||||
``by: string = ""``
|
``by: string = ""``
|
||||||
the string the substring is replaced with
|
the string the substring is replaced with
|
||||||
|
|
||||||
|
|
@ -71,7 +71,7 @@ Parameters and their defaults:
|
||||||
|
|
||||||
``leading: bool = true``
|
``leading: bool = true``
|
||||||
strip leading whitespace
|
strip leading whitespace
|
||||||
|
|
||||||
``trailing: bool = true``
|
``trailing: bool = true``
|
||||||
strip trailing whitespace
|
strip trailing whitespace
|
||||||
|
|
||||||
|
|
@ -89,16 +89,16 @@ Parameters and their defaults:
|
||||||
|
|
||||||
``metaChar: char = '#'``
|
``metaChar: char = '#'``
|
||||||
prefix for a line that contains Nim code
|
prefix for a line that contains Nim code
|
||||||
|
|
||||||
``subsChar: char = '$'``
|
``subsChar: char = '$'``
|
||||||
prefix for a Nim expression within a template line
|
prefix for a Nim expression within a template line
|
||||||
|
|
||||||
``conc: string = " & "``
|
``conc: string = " & "``
|
||||||
the operation for concatenation
|
the operation for concatenation
|
||||||
|
|
||||||
``emit: string = "result.add"``
|
``emit: string = "result.add"``
|
||||||
the operation to emit a string literal
|
the operation to emit a string literal
|
||||||
|
|
||||||
``toString: string = "$"``
|
``toString: string = "$"``
|
||||||
the operation that is applied to each expression
|
the operation that is applied to each expression
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ Example::
|
||||||
|
|
||||||
#! stdtmpl | standard
|
#! stdtmpl | standard
|
||||||
#proc generateHTMLPage(title, currentTab, content: string,
|
#proc generateHTMLPage(title, currentTab, content: string,
|
||||||
# tabs: openArray[string]): string =
|
# tabs: openArray[string]): string =
|
||||||
# result = ""
|
# result = ""
|
||||||
<head><title>$title</title></head>
|
<head><title>$title</title></head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -114,7 +114,7 @@ Example::
|
||||||
<ul>
|
<ul>
|
||||||
#for tab in items(tabs):
|
#for tab in items(tabs):
|
||||||
#if currentTab == tab:
|
#if currentTab == tab:
|
||||||
<li><a id="selected"
|
<li><a id="selected"
|
||||||
#else:
|
#else:
|
||||||
<li><a
|
<li><a
|
||||||
#end if
|
#end if
|
||||||
|
|
@ -132,11 +132,11 @@ The filter transforms this into:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
proc generateHTMLPage(title, currentTab, content: string,
|
proc generateHTMLPage(title, currentTab, content: string,
|
||||||
tabs: openArray[string]): string =
|
tabs: openArray[string]): string =
|
||||||
result = ""
|
result = ""
|
||||||
result.add("<head><title>" & $(title) & "</title></head>\n" &
|
result.add("<head><title>" & $(title) & "</title></head>\n" &
|
||||||
"<body>\n" &
|
"<body>\n" &
|
||||||
" <div id=\"menu\">\n" &
|
" <div id=\"menu\">\n" &
|
||||||
" <ul>\n")
|
" <ul>\n")
|
||||||
for tab in items(tabs):
|
for tab in items(tabs):
|
||||||
if currentTab == tab:
|
if currentTab == tab:
|
||||||
|
|
@ -146,17 +146,17 @@ The filter transforms this into:
|
||||||
#end
|
#end
|
||||||
result.add(" href=\"" & $(tab) & ".html\">" & $(tab) & "</a></li>\n")
|
result.add(" href=\"" & $(tab) & ".html\">" & $(tab) & "</a></li>\n")
|
||||||
#end
|
#end
|
||||||
result.add(" </ul>\n" &
|
result.add(" </ul>\n" &
|
||||||
" </div>\n" &
|
" </div>\n" &
|
||||||
" <div id=\"content\">\n" &
|
" <div id=\"content\">\n" &
|
||||||
" " & $(content) & "\n" &
|
" " & $(content) & "\n" &
|
||||||
" A dollar: $.\n" &
|
" A dollar: $.\n" &
|
||||||
" </div>\n" &
|
" </div>\n" &
|
||||||
"</body>\n")
|
"</body>\n")
|
||||||
|
|
||||||
|
|
||||||
Each line that does not start with the meta character (ignoring leading
|
Each line that does not start with the meta character (ignoring leading
|
||||||
whitespace) is converted to a string literal that is added to ``result``.
|
whitespace) is converted to a string literal that is added to ``result``.
|
||||||
|
|
||||||
The substitution character introduces a Nim expression *e* within the
|
The substitution character introduces a Nim expression *e* within the
|
||||||
string literal. *e* is converted to a string with the *toString* operation
|
string literal. *e* is converted to a string with the *toString* operation
|
||||||
|
|
@ -174,14 +174,14 @@ writes the template code directly to a file::
|
||||||
|
|
||||||
#! stdtmpl(emit="f.write") | standard
|
#! stdtmpl(emit="f.write") | standard
|
||||||
#proc writeHTMLPage(f: File, title, currentTab, content: string,
|
#proc writeHTMLPage(f: File, title, currentTab, content: string,
|
||||||
# tabs: openArray[string]) =
|
# tabs: openArray[string]) =
|
||||||
<head><title>$title</title></head>
|
<head><title>$title</title></head>
|
||||||
<body>
|
<body>
|
||||||
<div id="menu">
|
<div id="menu">
|
||||||
<ul>
|
<ul>
|
||||||
#for tab in items(tabs):
|
#for tab in items(tabs):
|
||||||
#if currentTab == tab:
|
#if currentTab == tab:
|
||||||
<li><a id="selected"
|
<li><a id="selected"
|
||||||
#else:
|
#else:
|
||||||
<li><a
|
<li><a
|
||||||
#end if
|
#end if
|
||||||
|
|
|
||||||
28
doc/gc.txt
28
doc/gc.txt
|
|
@ -37,13 +37,13 @@ The cycle collector can be en-/disabled independently from the other parts of
|
||||||
the GC with ``GC_enableMarkAndSweep`` and ``GC_disableMarkAndSweep``. The
|
the GC with ``GC_enableMarkAndSweep`` and ``GC_disableMarkAndSweep``. The
|
||||||
compiler analyses the types for their possibility to build cycles, but often
|
compiler analyses the types for their possibility to build cycles, but often
|
||||||
it is necessary to help this analysis with the ``acyclic`` pragma (see
|
it is necessary to help this analysis with the ``acyclic`` pragma (see
|
||||||
`acyclic <manual.html#acyclic-pragma>`_ for further information).
|
`acyclic <manual.html#acyclic-pragma>`_ for further information).
|
||||||
|
|
||||||
You can also use the ``acyclic`` pragma for data that is cyclic in reality and
|
You can also use the ``acyclic`` pragma for data that is cyclic in reality and
|
||||||
then break up the cycles explicitly with ``GC_addCycleRoot``. This can be a
|
then break up the cycles explicitly with ``GC_addCycleRoot``. This can be a
|
||||||
very valuable optimization; the Nim compiler itself relies on this
|
very valuable optimization; the Nim compiler itself relies on this
|
||||||
optimization trick to improve performance. Note that ``GC_addCycleRoot`` is
|
optimization trick to improve performance. Note that ``GC_addCycleRoot`` is
|
||||||
a quick operation; the root is only registered for the next run of the
|
a quick operation; the root is only registered for the next run of the
|
||||||
cycle collector.
|
cycle collector.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@ Realtime support
|
||||||
================
|
================
|
||||||
|
|
||||||
To enable realtime support, the symbol `useRealtimeGC`:idx: needs to be
|
To enable realtime support, the symbol `useRealtimeGC`:idx: needs to be
|
||||||
defined via ``--define:useRealtimeGC`` (you can put this into your config
|
defined via ``--define:useRealtimeGC`` (you can put this into your config
|
||||||
file as well). With this switch the GC supports the following operations:
|
file as well). With this switch the GC supports the following operations:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -60,21 +60,21 @@ file as well). With this switch the GC supports the following operations:
|
||||||
|
|
||||||
The unit of the parameters ``MaxPauseInUs`` and ``us`` is microseconds.
|
The unit of the parameters ``MaxPauseInUs`` and ``us`` is microseconds.
|
||||||
|
|
||||||
These two procs are the two modus operandi of the realtime GC:
|
These two procs are the two modus operandi of the realtime GC:
|
||||||
|
|
||||||
(1) GC_SetMaxPause Mode
|
(1) GC_SetMaxPause Mode
|
||||||
|
|
||||||
You can call ``GC_SetMaxPause`` at program startup and then each triggered
|
You can call ``GC_SetMaxPause`` at program startup and then each triggered
|
||||||
GC run tries to not take longer than ``MaxPause`` time. However, it is
|
GC run tries to not take longer than ``MaxPause`` time. However, it is
|
||||||
possible (and common) that the work is nevertheless not evenly distributed
|
possible (and common) that the work is nevertheless not evenly distributed
|
||||||
as each call to ``new`` can trigger the GC and thus take ``MaxPause``
|
as each call to ``new`` can trigger the GC and thus take ``MaxPause``
|
||||||
time.
|
time.
|
||||||
|
|
||||||
(2) GC_step Mode
|
(2) GC_step Mode
|
||||||
|
|
||||||
This allows the GC to perform some work for up to ``us`` time. This is
|
This allows the GC to perform some work for up to ``us`` time. This is
|
||||||
useful to call in a main loop to ensure the GC can do its work. To
|
useful to call in a main loop to ensure the GC can do its work. To
|
||||||
bind all GC activity to a ``GC_step`` call, deactivate the GC with
|
bind all GC activity to a ``GC_step`` call, deactivate the GC with
|
||||||
``GC_disable`` at program startup.
|
``GC_disable`` at program startup.
|
||||||
|
|
||||||
These procs provide a "best effort" realtime guarantee; in particular the
|
These procs provide a "best effort" realtime guarantee; in particular the
|
||||||
|
|
@ -87,7 +87,7 @@ is triggered.
|
||||||
Time measurement
|
Time measurement
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
The GC's way of measuring time uses (see ``lib/system/timers.nim`` for the
|
The GC's way of measuring time uses (see ``lib/system/timers.nim`` for the
|
||||||
implementation):
|
implementation):
|
||||||
|
|
||||||
1) ``QueryPerformanceCounter`` and ``QueryPerformanceFrequency`` on Windows.
|
1) ``QueryPerformanceCounter`` and ``QueryPerformanceFrequency`` on Windows.
|
||||||
|
|
@ -95,7 +95,7 @@ implementation):
|
||||||
3) ``gettimeofday`` on Posix systems.
|
3) ``gettimeofday`` on Posix systems.
|
||||||
|
|
||||||
As such it supports a resolution of nanoseconds internally; however the API
|
As such it supports a resolution of nanoseconds internally; however the API
|
||||||
uses microseconds for convenience.
|
uses microseconds for convenience.
|
||||||
|
|
||||||
|
|
||||||
Define the symbol ``reportMissedDeadlines`` to make the GC output whenever it
|
Define the symbol ``reportMissedDeadlines`` to make the GC output whenever it
|
||||||
|
|
@ -106,7 +106,7 @@ later versions of the collector.
|
||||||
Tweaking the GC
|
Tweaking the GC
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
The collector checks whether there is still time left for its work after
|
The collector checks whether there is still time left for its work after
|
||||||
every ``workPackage``'th iteration. This is currently set to 100 which means
|
every ``workPackage``'th iteration. This is currently set to 100 which means
|
||||||
that up to 100 objects are traversed and freed before it checks again. Thus
|
that up to 100 objects are traversed and freed before it checks again. Thus
|
||||||
``workPackage`` affects the timing granularity and may need to be tweaked in
|
``workPackage`` affects the timing granularity and may need to be tweaked in
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ Path Purpose
|
||||||
``bin`` generated binary files
|
``bin`` generated binary files
|
||||||
``build`` generated C code for the installation
|
``build`` generated C code for the installation
|
||||||
``compiler`` the Nim compiler itself; note that this
|
``compiler`` the Nim compiler itself; note that this
|
||||||
code has been translated from a bootstrapping
|
code has been translated from a bootstrapping
|
||||||
version written in Pascal, so the code is **not**
|
version written in Pascal, so the code is **not**
|
||||||
a poster child of good Nim code
|
a poster child of good Nim code
|
||||||
``config`` configuration files for Nim
|
``config`` configuration files for Nim
|
||||||
``dist`` additional packages for the distribution
|
``dist`` additional packages for the distribution
|
||||||
|
|
@ -38,8 +38,8 @@ Path Purpose
|
||||||
Bootstrapping the compiler
|
Bootstrapping the compiler
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
As of version 0.8.5 the compiler is maintained in Nim. (The first versions
|
As of version 0.8.5 the compiler is maintained in Nim. (The first versions
|
||||||
have been implemented in Object Pascal.) The Python-based build system has
|
have been implemented in Object Pascal.) The Python-based build system has
|
||||||
been rewritten in Nim too.
|
been rewritten in Nim too.
|
||||||
|
|
||||||
Compiling the compiler is a simple matter of running::
|
Compiling the compiler is a simple matter of running::
|
||||||
|
|
@ -121,7 +121,7 @@ Look at the file ``lib/system/hti.nim`` for more information.
|
||||||
Debugging the compiler
|
Debugging the compiler
|
||||||
======================
|
======================
|
||||||
|
|
||||||
You can of course use GDB or Visual Studio to debug the
|
You can of course use GDB or Visual Studio to debug the
|
||||||
compiler (via ``--debuginfo --lineDir:on``). However, there
|
compiler (via ``--debuginfo --lineDir:on``). However, there
|
||||||
are also lots of procs that aid in debugging:
|
are also lots of procs that aid in debugging:
|
||||||
|
|
||||||
|
|
@ -180,7 +180,7 @@ children. Types and symbols are represented by other nodes, because they
|
||||||
may contain cycles. The AST changes its shape after semantic checking. This
|
may contain cycles. The AST changes its shape after semantic checking. This
|
||||||
is needed to make life easier for the code generators. See the "ast" module
|
is needed to make life easier for the code generators. See the "ast" module
|
||||||
for the type definitions. The `macros <macros.html>`_ module contains many
|
for the type definitions. The `macros <macros.html>`_ module contains many
|
||||||
examples how the AST represents each syntactic structure.
|
examples how the AST represents each syntactic structure.
|
||||||
|
|
||||||
|
|
||||||
How the RTL is compiled
|
How the RTL is compiled
|
||||||
|
|
@ -202,7 +202,7 @@ Compilation cache
|
||||||
=================
|
=================
|
||||||
|
|
||||||
The implementation of the compilation cache is tricky: There are lots
|
The implementation of the compilation cache is tricky: There are lots
|
||||||
of issues to be solved for the front- and backend. In the following
|
of issues to be solved for the front- and backend. In the following
|
||||||
sections *global* means *shared between modules* or *property of the whole
|
sections *global* means *shared between modules* or *property of the whole
|
||||||
program*.
|
program*.
|
||||||
|
|
||||||
|
|
@ -214,31 +214,31 @@ Methods and type converters
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Nim contains language features that are *global*. The best example for that
|
Nim contains language features that are *global*. The best example for that
|
||||||
are multi methods: Introducing a new method with the same name and some
|
are multi methods: Introducing a new method with the same name and some
|
||||||
compatible object parameter means that the method's dispatcher needs to take
|
compatible object parameter means that the method's dispatcher needs to take
|
||||||
the new method into account. So the dispatching logic is only completely known
|
the new method into account. So the dispatching logic is only completely known
|
||||||
after the whole program has been translated!
|
after the whole program has been translated!
|
||||||
|
|
||||||
Other features that are *implicitly* triggered cause problems for modularity
|
Other features that are *implicitly* triggered cause problems for modularity
|
||||||
too. Type converters fall into this category:
|
too. Type converters fall into this category:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
# module A
|
# module A
|
||||||
converter toBool(x: int): bool =
|
converter toBool(x: int): bool =
|
||||||
result = x != 0
|
result = x != 0
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
# module B
|
# module B
|
||||||
import A
|
import A
|
||||||
|
|
||||||
if 1:
|
if 1:
|
||||||
echo "ugly, but should work"
|
echo "ugly, but should work"
|
||||||
|
|
||||||
If in the above example module ``B`` is re-compiled, but ``A`` is not then
|
If in the above example module ``B`` is re-compiled, but ``A`` is not then
|
||||||
``B`` needs to be aware of ``toBool`` even though ``toBool`` is not referenced
|
``B`` needs to be aware of ``toBool`` even though ``toBool`` is not referenced
|
||||||
in ``B`` *explicitly*.
|
in ``B`` *explicitly*.
|
||||||
|
|
||||||
Both the multi method and the type converter problems are solved by storing
|
Both the multi method and the type converter problems are solved by storing
|
||||||
them in special sections in the ROD file that are loaded *unconditionally*
|
them in special sections in the ROD file that are loaded *unconditionally*
|
||||||
when the ROD file is read.
|
when the ROD file is read.
|
||||||
|
|
||||||
|
|
@ -266,7 +266,7 @@ Backend issues
|
||||||
- Emulated thread vars are global.
|
- Emulated thread vars are global.
|
||||||
|
|
||||||
|
|
||||||
However the biggest problem is that dead code elimination breaks modularity!
|
However the biggest problem is that dead code elimination breaks modularity!
|
||||||
To see why, consider this scenario: The module ``G`` (for example the huge
|
To see why, consider this scenario: The module ``G`` (for example the huge
|
||||||
Gtk2 module...) is compiled with dead code elimination turned on. So none
|
Gtk2 module...) is compiled with dead code elimination turned on. So none
|
||||||
of ``G``'s procs is generated at all.
|
of ``G``'s procs is generated at all.
|
||||||
|
|
@ -274,13 +274,13 @@ of ``G``'s procs is generated at all.
|
||||||
Then module ``B`` is compiled that requires ``G.P1``. Ok, no problem,
|
Then module ``B`` is compiled that requires ``G.P1``. Ok, no problem,
|
||||||
``G.P1`` is loaded from the symbol file and ``G.c`` now contains ``G.P1``.
|
``G.P1`` is loaded from the symbol file and ``G.c`` now contains ``G.P1``.
|
||||||
|
|
||||||
Then module ``A`` (that depends onto ``B`` and ``G``) is compiled and ``B``
|
Then module ``A`` (that depends onto ``B`` and ``G``) is compiled and ``B``
|
||||||
and ``G`` are left unchanged. ``A`` requires ``G.P2``.
|
and ``G`` are left unchanged. ``A`` requires ``G.P2``.
|
||||||
|
|
||||||
So now ``G.c`` MUST contain both ``P1`` and ``P2``, but we haven't even
|
So now ``G.c`` MUST contain both ``P1`` and ``P2``, but we haven't even
|
||||||
loaded ``P1`` from the symbol file, nor do we want to because we then quickly
|
loaded ``P1`` from the symbol file, nor do we want to because we then quickly
|
||||||
would restore large parts of the whole program. But we also don't want to
|
would restore large parts of the whole program. But we also don't want to
|
||||||
store ``P1`` in ``B.c`` because that would mean to store every symbol where
|
store ``P1`` in ``B.c`` because that would mean to store every symbol where
|
||||||
it is referred from which ultimately means the main module and putting
|
it is referred from which ultimately means the main module and putting
|
||||||
everything in a single C file.
|
everything in a single C file.
|
||||||
|
|
||||||
|
|
@ -290,7 +290,7 @@ that is implemented in the C code generator (have a look at the ``ccgmerge``
|
||||||
module). The merging may lead to *cruft* (aka dead code) in generated C code
|
module). The merging may lead to *cruft* (aka dead code) in generated C code
|
||||||
which can only be removed by recompiling a project with the compilation cache
|
which can only be removed by recompiling a project with the compilation cache
|
||||||
turned off. Nevertheless the merge solution is way superior to the
|
turned off. Nevertheless the merge solution is way superior to the
|
||||||
cheap solution "turn off dead code elimination if the compilation cache is
|
cheap solution "turn off dead code elimination if the compilation cache is
|
||||||
turned on".
|
turned on".
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -394,7 +394,7 @@ Consider this example:
|
||||||
# r is on the stack
|
# r is on the stack
|
||||||
setRef(r.left) # here we should update the refcounts!
|
setRef(r.left) # here we should update the refcounts!
|
||||||
|
|
||||||
We have to decide at runtime whether the reference is on the stack or not.
|
We have to decide at runtime whether the reference is on the stack or not.
|
||||||
The generated code looks roughly like this:
|
The generated code looks roughly like this:
|
||||||
|
|
||||||
.. code-block:: C
|
.. code-block:: C
|
||||||
|
|
@ -422,7 +422,7 @@ Design
|
||||||
A ``closure`` proc var can call ordinary procs of the default Nim calling
|
A ``closure`` proc var can call ordinary procs of the default Nim calling
|
||||||
convention. But not the other way round! A closure is implemented as a
|
convention. But not the other way round! A closure is implemented as a
|
||||||
``tuple[prc, env]``. ``env`` can be nil implying a call without a closure.
|
``tuple[prc, env]``. ``env`` can be nil implying a call without a closure.
|
||||||
This means that a call through a closure generates an ``if`` but the
|
This means that a call through a closure generates an ``if`` but the
|
||||||
interoperability is worth the cost of the ``if``. Thunk generation would be
|
interoperability is worth the cost of the ``if``. Thunk generation would be
|
||||||
possible too, but it's slightly more effort to implement.
|
possible too, but it's slightly more effort to implement.
|
||||||
|
|
||||||
|
|
@ -430,7 +430,7 @@ Tests with GCC on Amd64 showed that it's really beneficical if the
|
||||||
'environment' pointer is passed as the last argument, not as the first argument.
|
'environment' pointer is passed as the last argument, not as the first argument.
|
||||||
|
|
||||||
Proper thunk generation is harder because the proc that is to wrap
|
Proper thunk generation is harder because the proc that is to wrap
|
||||||
could stem from a complex expression:
|
could stem from a complex expression:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
receivesClosure(returnsDefaultCC[i])
|
receivesClosure(returnsDefaultCC[i])
|
||||||
|
|
@ -438,15 +438,15 @@ could stem from a complex expression:
|
||||||
A thunk would need to call 'returnsDefaultCC[i]' somehow and that would require
|
A thunk would need to call 'returnsDefaultCC[i]' somehow and that would require
|
||||||
an *additional* closure generation... Ok, not really, but it requires to pass
|
an *additional* closure generation... Ok, not really, but it requires to pass
|
||||||
the function to call. So we'd end up with 2 indirect calls instead of one.
|
the function to call. So we'd end up with 2 indirect calls instead of one.
|
||||||
Another much more severe problem which this solution is that it's not GC-safe
|
Another much more severe problem which this solution is that it's not GC-safe
|
||||||
to pass a proc pointer around via a generic ``ref`` type.
|
to pass a proc pointer around via a generic ``ref`` type.
|
||||||
|
|
||||||
|
|
||||||
Example code:
|
Example code:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
proc add(x: int): proc (y: int): int {.closure.} =
|
proc add(x: int): proc (y: int): int {.closure.} =
|
||||||
return proc (y: int): int =
|
return proc (y: int): int =
|
||||||
return x + y
|
return x + y
|
||||||
|
|
||||||
var add2 = add(2)
|
var add2 = add(2)
|
||||||
|
|
@ -458,16 +458,16 @@ This should produce roughly this code:
|
||||||
type
|
type
|
||||||
PEnv = ref object
|
PEnv = ref object
|
||||||
x: int # data
|
x: int # data
|
||||||
|
|
||||||
proc anon(y: int, c: PClosure): int =
|
proc anon(y: int, c: PClosure): int =
|
||||||
return y + c.x
|
return y + c.x
|
||||||
|
|
||||||
proc add(x: int): tuple[prc, data] =
|
proc add(x: int): tuple[prc, data] =
|
||||||
var env: PEnv
|
var env: PEnv
|
||||||
new env
|
new env
|
||||||
env.x = x
|
env.x = x
|
||||||
result = (anon, env)
|
result = (anon, env)
|
||||||
|
|
||||||
var add2 = add(2)
|
var add2 = add(2)
|
||||||
let tmp = if add2.data == nil: add2.prc(5) else: add2.prc(5, add2.data)
|
let tmp = if add2.data == nil: add2.prc(5) else: add2.prc(5, add2.data)
|
||||||
echo tmp
|
echo tmp
|
||||||
|
|
@ -476,9 +476,9 @@ This should produce roughly this code:
|
||||||
Beware of nesting:
|
Beware of nesting:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
proc add(x: int): proc (y: int): proc (z: int): int {.closure.} {.closure.} =
|
proc add(x: int): proc (y: int): proc (z: int): int {.closure.} {.closure.} =
|
||||||
return lamba (y: int): proc (z: int): int {.closure.} =
|
return lamba (y: int): proc (z: int): int {.closure.} =
|
||||||
return lambda (z: int): int =
|
return lambda (z: int): int =
|
||||||
return x + y + z
|
return x + y + z
|
||||||
|
|
||||||
var add24 = add(2)(4)
|
var add24 = add(2)(4)
|
||||||
|
|
@ -490,26 +490,26 @@ This should produce roughly this code:
|
||||||
type
|
type
|
||||||
PEnvX = ref object
|
PEnvX = ref object
|
||||||
x: int # data
|
x: int # data
|
||||||
|
|
||||||
PEnvY = ref object
|
PEnvY = ref object
|
||||||
y: int
|
y: int
|
||||||
ex: PEnvX
|
ex: PEnvX
|
||||||
|
|
||||||
proc lambdaZ(z: int, ey: PEnvY): int =
|
proc lambdaZ(z: int, ey: PEnvY): int =
|
||||||
return ey.ex.x + ey.y + z
|
return ey.ex.x + ey.y + z
|
||||||
|
|
||||||
proc lambdaY(y: int, ex: PEnvX): tuple[prc, data: PEnvY] =
|
proc lambdaY(y: int, ex: PEnvX): tuple[prc, data: PEnvY] =
|
||||||
var ey: PEnvY
|
var ey: PEnvY
|
||||||
new ey
|
new ey
|
||||||
ey.y = y
|
ey.y = y
|
||||||
ey.ex = ex
|
ey.ex = ex
|
||||||
result = (lambdaZ, ey)
|
result = (lambdaZ, ey)
|
||||||
|
|
||||||
proc add(x: int): tuple[prc, data: PEnvX] =
|
proc add(x: int): tuple[prc, data: PEnvX] =
|
||||||
var ex: PEnvX
|
var ex: PEnvX
|
||||||
ex.x = x
|
ex.x = x
|
||||||
result = (labmdaY, ex)
|
result = (labmdaY, ex)
|
||||||
|
|
||||||
var tmp = add(2)
|
var tmp = add(2)
|
||||||
var tmp2 = tmp.fn(4, tmp.data)
|
var tmp2 = tmp.fn(4, tmp.data)
|
||||||
var add24 = tmp2.fn(4, tmp2.data)
|
var add24 = tmp2.fn(4, tmp2.data)
|
||||||
|
|
@ -517,14 +517,14 @@ This should produce roughly this code:
|
||||||
|
|
||||||
|
|
||||||
We could get rid of nesting environments by always inlining inner anon procs.
|
We could get rid of nesting environments by always inlining inner anon procs.
|
||||||
More useful is escape analysis and stack allocation of the environment,
|
More useful is escape analysis and stack allocation of the environment,
|
||||||
however.
|
however.
|
||||||
|
|
||||||
|
|
||||||
Alternative
|
Alternative
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
Process the closure of all inner procs in one pass and accumulate the
|
Process the closure of all inner procs in one pass and accumulate the
|
||||||
environments. This is however not always possible.
|
environments. This is however not always possible.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -532,21 +532,21 @@ Accumulator
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
proc getAccumulator(start: int): proc (): int {.closure} =
|
proc getAccumulator(start: int): proc (): int {.closure} =
|
||||||
var i = start
|
var i = start
|
||||||
return lambda: int =
|
return lambda: int =
|
||||||
inc i
|
inc i
|
||||||
return i
|
return i
|
||||||
|
|
||||||
proc p =
|
proc p =
|
||||||
var delta = 7
|
var delta = 7
|
||||||
proc accumulator(start: int): proc(): int =
|
proc accumulator(start: int): proc(): int =
|
||||||
var x = start-1
|
var x = start-1
|
||||||
result = proc (): int =
|
result = proc (): int =
|
||||||
x = x + delta
|
x = x + delta
|
||||||
inc delta
|
inc delta
|
||||||
return x
|
return x
|
||||||
|
|
||||||
var a = accumulator(3)
|
var a = accumulator(3)
|
||||||
var b = accumulator(4)
|
var b = accumulator(4)
|
||||||
echo a() + b()
|
echo a() + b()
|
||||||
|
|
@ -560,7 +560,7 @@ pass generates code to setup the environment and to pass it around. However,
|
||||||
this pass does not change the types! So we have some kind of mismatch here; on
|
this pass does not change the types! So we have some kind of mismatch here; on
|
||||||
the one hand the proc expression becomes an explicit tuple, on the other hand
|
the one hand the proc expression becomes an explicit tuple, on the other hand
|
||||||
the tyProc(ccClosure) type is not changed. For C code generation it's also
|
the tyProc(ccClosure) type is not changed. For C code generation it's also
|
||||||
important the hidden formal param is ``void*`` and not something more
|
important the hidden formal param is ``void*`` and not something more
|
||||||
specialized. However the more specialized env type needs to passed to the
|
specialized. However the more specialized env type needs to passed to the
|
||||||
backend somehow. We deal with this by modifying ``s.ast[paramPos]`` to contain
|
backend somehow. We deal with this by modifying ``s.ast[paramPos]`` to contain
|
||||||
the formal hidden parameter, but not ``s.typ``!
|
the formal hidden parameter, but not ``s.typ``!
|
||||||
|
|
|
||||||
|
|
@ -14,20 +14,20 @@ optional *a*. Parentheses may be used to group elements.
|
||||||
``&`` is the lookahead operator; ``&a`` means that an ``a`` is expected but
|
``&`` is the lookahead operator; ``&a`` means that an ``a`` is expected but
|
||||||
not consumed. It will be consumed in the following rule.
|
not consumed. It will be consumed in the following rule.
|
||||||
|
|
||||||
The ``|``, ``/`` symbols are used to mark alternatives and have the lowest
|
The ``|``, ``/`` symbols are used to mark alternatives and have the lowest
|
||||||
precedence. ``/`` is the ordered choice that requires the parser to try the
|
precedence. ``/`` is the ordered choice that requires the parser to try the
|
||||||
alternatives in the given order. ``/`` is often used to ensure the grammar
|
alternatives in the given order. ``/`` is often used to ensure the grammar
|
||||||
is not ambiguous.
|
is not ambiguous.
|
||||||
|
|
||||||
Non-terminals start with a lowercase letter, abstract terminal symbols are in
|
Non-terminals start with a lowercase letter, abstract terminal symbols are in
|
||||||
UPPERCASE. Verbatim terminal symbols (including keywords) are quoted
|
UPPERCASE. Verbatim terminal symbols (including keywords) are quoted
|
||||||
with ``'``. An example::
|
with ``'``. An example::
|
||||||
|
|
||||||
ifStmt = 'if' expr ':' stmts ('elif' expr ':' stmts)* ('else' stmts)?
|
ifStmt = 'if' expr ':' stmts ('elif' expr ':' stmts)* ('else' stmts)?
|
||||||
|
|
||||||
The binary ``^*`` operator is used as a shorthand for 0 or more occurrences
|
The binary ``^*`` operator is used as a shorthand for 0 or more occurrences
|
||||||
separated by its second argument; likewise ``^+`` means 1 or more
|
separated by its second argument; likewise ``^+`` means 1 or more
|
||||||
occurrences: ``a ^+ b`` is short for ``a (b a)*``
|
occurrences: ``a ^+ b`` is short for ``a (b a)*``
|
||||||
and ``a ^* b`` is short for ``(a (b a)*)?``. Example::
|
and ``a ^* b`` is short for ``(a (b a)*)?``. Example::
|
||||||
|
|
||||||
arrayConstructor = '[' expr ^* ',' ']'
|
arrayConstructor = '[' expr ^* ',' ']'
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@ program execution. Unless explicitly classified, an error is a static error.
|
||||||
|
|
||||||
A `checked runtime error`:idx: is an error that the implementation detects
|
A `checked runtime error`:idx: is an error that the implementation detects
|
||||||
and reports at runtime. The method for reporting such errors is via *raising
|
and reports at runtime. The method for reporting such errors is via *raising
|
||||||
exceptions* or *dying with a fatal error*. However, the implementation
|
exceptions* or *dying with a fatal error*. However, the implementation
|
||||||
provides a means to disable these runtime checks. See the section pragmas_
|
provides a means to disable these runtime checks. See the section pragmas_
|
||||||
for details.
|
for details.
|
||||||
|
|
||||||
Whether a checked runtime error results in an exception or in a fatal error at
|
Whether a checked runtime error results in an exception or in a fatal error at
|
||||||
runtime is implementation specific. Thus the following program is always
|
runtime is implementation specific. Thus the following program is always
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ Exception tracking
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
Nim supports exception tracking. The `raises`:idx: pragma can be used
|
Nim supports exception tracking. The `raises`:idx: pragma can be used
|
||||||
to explicitly define which exceptions a proc/iterator/method/converter is
|
to explicitly define which exceptions a proc/iterator/method/converter is
|
||||||
allowed to raise. The compiler verifies this:
|
allowed to raise. The compiler verifies this:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -24,7 +24,7 @@ An empty ``raises`` list (``raises: []``) means that no exception may be raised:
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
|
|
||||||
A ``raises`` list can also be attached to a proc type. This affects type
|
A ``raises`` list can also be attached to a proc type. This affects type
|
||||||
compatibility:
|
compatibility:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -35,7 +35,7 @@ compatibility:
|
||||||
|
|
||||||
proc p(x: string) =
|
proc p(x: string) =
|
||||||
raise newException(OSError, "OS")
|
raise newException(OSError, "OS")
|
||||||
|
|
||||||
c = p # type error
|
c = p # type error
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -46,30 +46,30 @@ possibly raised exceptions; the algorithm operates on ``p``'s call graph:
|
||||||
raise ``system.Exception`` (the base type of the exception hierarchy) and
|
raise ``system.Exception`` (the base type of the exception hierarchy) and
|
||||||
thus any exception unless ``T`` has an explicit ``raises`` list.
|
thus any exception unless ``T`` has an explicit ``raises`` list.
|
||||||
However if the call is of the form ``f(...)`` where ``f`` is a parameter
|
However if the call is of the form ``f(...)`` where ``f`` is a parameter
|
||||||
of the currently analysed routine it is ignored. The call is optimistically
|
of the currently analysed routine it is ignored. The call is optimistically
|
||||||
assumed to have no effect. Rule 2 compensates for this case.
|
assumed to have no effect. Rule 2 compensates for this case.
|
||||||
2. Every expression of some proc type within a call that is not a call
|
2. Every expression of some proc type within a call that is not a call
|
||||||
itself (and not nil) is assumed to be called indirectly somehow and thus
|
itself (and not nil) is assumed to be called indirectly somehow and thus
|
||||||
its raises list is added to ``p``'s raises list.
|
its raises list is added to ``p``'s raises list.
|
||||||
3. Every call to a proc ``q`` which has an unknown body (due to a forward
|
3. Every call to a proc ``q`` which has an unknown body (due to a forward
|
||||||
declaration or an ``importc`` pragma) is assumed to
|
declaration or an ``importc`` pragma) is assumed to
|
||||||
raise ``system.Exception`` unless ``q`` has an explicit ``raises`` list.
|
raise ``system.Exception`` unless ``q`` has an explicit ``raises`` list.
|
||||||
4. Every call to a method ``m`` is assumed to
|
4. Every call to a method ``m`` is assumed to
|
||||||
raise ``system.Exception`` unless ``m`` has an explicit ``raises`` list.
|
raise ``system.Exception`` unless ``m`` has an explicit ``raises`` list.
|
||||||
5. For every other call the analysis can determine an exact ``raises`` list.
|
5. For every other call the analysis can determine an exact ``raises`` list.
|
||||||
6. For determining a ``raises`` list, the ``raise`` and ``try`` statements
|
6. For determining a ``raises`` list, the ``raise`` and ``try`` statements
|
||||||
of ``p`` are taken into consideration.
|
of ``p`` are taken into consideration.
|
||||||
|
|
||||||
Rules 1-2 ensure the following works:
|
Rules 1-2 ensure the following works:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
proc noRaise(x: proc()) {.raises: [].} =
|
proc noRaise(x: proc()) {.raises: [].} =
|
||||||
# unknown call that might raise anything, but valid:
|
# unknown call that might raise anything, but valid:
|
||||||
x()
|
x()
|
||||||
|
|
||||||
proc doRaise() {.raises: [IOError].} =
|
proc doRaise() {.raises: [IOError].} =
|
||||||
raise newException(IOError, "IO")
|
raise newException(IOError, "IO")
|
||||||
|
|
||||||
proc use() {.raises: [].} =
|
proc use() {.raises: [].} =
|
||||||
# doesn't compile! Can raise IOError!
|
# doesn't compile! Can raise IOError!
|
||||||
noRaise(doRaise)
|
noRaise(doRaise)
|
||||||
|
|
@ -82,21 +82,21 @@ Tag tracking
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The exception tracking is part of Nim's `effect system`:idx:. Raising an
|
The exception tracking is part of Nim's `effect system`:idx:. Raising an
|
||||||
exception is an *effect*. Other effects can also be defined. A user defined
|
exception is an *effect*. Other effects can also be defined. A user defined
|
||||||
effect is a means to *tag* a routine and to perform checks against this tag:
|
effect is a means to *tag* a routine and to perform checks against this tag:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
type IO = object ## input/output effect
|
type IO = object ## input/output effect
|
||||||
proc readLine(): string {.tags: [IO].}
|
proc readLine(): string {.tags: [IO].}
|
||||||
|
|
||||||
proc no_IO_please() {.tags: [].} =
|
proc no_IO_please() {.tags: [].} =
|
||||||
# the compiler prevents this:
|
# the compiler prevents this:
|
||||||
let x = readLine()
|
let x = readLine()
|
||||||
|
|
||||||
A tag has to be a type name. A ``tags`` list - like a ``raises`` list - can
|
A tag has to be a type name. A ``tags`` list - like a ``raises`` list - can
|
||||||
also be attached to a proc type. This affects type compatibility.
|
also be attached to a proc type. This affects type compatibility.
|
||||||
|
|
||||||
The inference for tag tracking is analogous to the inference for
|
The inference for tag tracking is analogous to the inference for
|
||||||
exception tracking.
|
exception tracking.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ Read/Write tracking
|
||||||
|
|
||||||
**Note**: Read/write tracking is not yet implemented!
|
**Note**: Read/write tracking is not yet implemented!
|
||||||
|
|
||||||
The inference for read/write tracking is analogous to the inference for
|
The inference for read/write tracking is analogous to the inference for
|
||||||
exception tracking.
|
exception tracking.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@ Alternatively, the ``distinct`` type modifier can be applied to the type class
|
||||||
to allow each param matching the type class to bind to a different type.
|
to allow each param matching the type class to bind to a different type.
|
||||||
|
|
||||||
If a proc param doesn't have a type specified, Nim will use the
|
If a proc param doesn't have a type specified, Nim will use the
|
||||||
``distinct auto`` type class (also known as ``any``). Note this behavior is
|
``distinct auto`` type class (also known as ``any``). Note this behavior is
|
||||||
deprecated for procs; templates, however, support them:
|
deprecated for procs; templates, however, support them:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ With this notation we can now easily define the core of the grammar: A block of
|
||||||
statements (simplified example)::
|
statements (simplified example)::
|
||||||
|
|
||||||
ifStmt = 'if' expr ':' stmt
|
ifStmt = 'if' expr ':' stmt
|
||||||
(IND{=} 'elif' expr ':' stmt)*
|
(IND{=} 'elif' expr ':' stmt)*
|
||||||
(IND{=} 'else' ':' stmt)?
|
(IND{=} 'else' ':' stmt)?
|
||||||
|
|
||||||
simpleStmt = ifStmt / ...
|
simpleStmt = ifStmt / ...
|
||||||
|
|
@ -156,7 +156,7 @@ contain the following `escape sequences`:idx:\ :
|
||||||
================== ===================================================
|
================== ===================================================
|
||||||
|
|
||||||
|
|
||||||
Strings in Nim may contain any 8-bit value, even embedded zeros. However
|
Strings in Nim may contain any 8-bit value, even embedded zeros. However
|
||||||
some operations may interpret the first binary zero as a terminator.
|
some operations may interpret the first binary zero as a terminator.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -174,7 +174,7 @@ be whitespace between the opening ``"""`` and the newline),
|
||||||
the newline (and the preceding whitespace) is not included in the string. The
|
the newline (and the preceding whitespace) is not included in the string. The
|
||||||
ending of the string literal is defined by the pattern ``"""[^"]``, so this:
|
ending of the string literal is defined by the pattern ``"""[^"]``, so this:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
""""long string within quotes""""
|
""""long string within quotes""""
|
||||||
|
|
||||||
Produces::
|
Produces::
|
||||||
|
|
@ -187,9 +187,9 @@ Raw string literals
|
||||||
|
|
||||||
Terminal symbol in the grammar: ``RSTR_LIT``.
|
Terminal symbol in the grammar: ``RSTR_LIT``.
|
||||||
|
|
||||||
There are also raw string literals that are preceded with the
|
There are also raw string literals that are preceded with the
|
||||||
letter ``r`` (or ``R``) and are delimited by matching double quotes (just
|
letter ``r`` (or ``R``) and are delimited by matching double quotes (just
|
||||||
like ordinary string literals) and do not interpret the escape sequences.
|
like ordinary string literals) and do not interpret the escape sequences.
|
||||||
This is especially convenient for regular expressions or Windows paths:
|
This is especially convenient for regular expressions or Windows paths:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -201,21 +201,21 @@ To produce a single ``"`` within a raw string literal, it has to be doubled:
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
r"a""b"
|
r"a""b"
|
||||||
|
|
||||||
Produces::
|
Produces::
|
||||||
|
|
||||||
a"b
|
a"b
|
||||||
|
|
||||||
``r""""`` is not possible with this notation, because the three leading
|
``r""""`` is not possible with this notation, because the three leading
|
||||||
quotes introduce a triple quoted string literal. ``r"""`` is the same
|
quotes introduce a triple quoted string literal. ``r"""`` is the same
|
||||||
as ``"""`` since triple quoted string literals do not interpret escape
|
as ``"""`` since triple quoted string literals do not interpret escape
|
||||||
sequences either.
|
sequences either.
|
||||||
|
|
||||||
|
|
||||||
Generalized raw string literals
|
Generalized raw string literals
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
Terminal symbols in the grammar: ``GENERALIZED_STR_LIT``,
|
Terminal symbols in the grammar: ``GENERALIZED_STR_LIT``,
|
||||||
``GENERALIZED_TRIPLESTR_LIT``.
|
``GENERALIZED_TRIPLESTR_LIT``.
|
||||||
|
|
||||||
The construct ``identifier"string literal"`` (without whitespace between the
|
The construct ``identifier"string literal"`` (without whitespace between the
|
||||||
|
|
@ -281,7 +281,7 @@ Numerical constants are of a single type and have the form::
|
||||||
DEC_LIT = digit ( ['_'] digit )*
|
DEC_LIT = digit ( ['_'] digit )*
|
||||||
OCT_LIT = '0' ('o' | 'c' | 'C') octdigit ( ['_'] octdigit )*
|
OCT_LIT = '0' ('o' | 'c' | 'C') octdigit ( ['_'] octdigit )*
|
||||||
BIN_LIT = '0' ('b' | 'B' ) bindigit ( ['_'] bindigit )*
|
BIN_LIT = '0' ('b' | 'B' ) bindigit ( ['_'] bindigit )*
|
||||||
|
|
||||||
INT_LIT = HEX_LIT
|
INT_LIT = HEX_LIT
|
||||||
| DEC_LIT
|
| DEC_LIT
|
||||||
| OCT_LIT
|
| OCT_LIT
|
||||||
|
|
@ -383,7 +383,7 @@ The following strings denote other tokens::
|
||||||
` ( ) { } [ ] , ; [. .] {. .} (. .)
|
` ( ) { } [ ] , ; [. .] {. .} (. .)
|
||||||
|
|
||||||
|
|
||||||
The `slice`:idx: operator `..`:tok: takes precedence over other tokens that
|
The `slice`:idx: operator `..`:tok: takes precedence over other tokens that
|
||||||
contain a dot: `{..}`:tok: are the three tokens `{`:tok:, `..`:tok:, `}`:tok:
|
contain a dot: `{..}`:tok: are the three tokens `{`:tok:, `..`:tok:, `}`:tok:
|
||||||
and not the two tokens `{.`:tok:, `.}`:tok:.
|
and not the two tokens `{.`:tok:, `.}`:tok:.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ model low level lockfree mechanisms:
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
var dummyLock {.compileTime.}: int
|
var dummyLock {.compileTime.}: int
|
||||||
var atomicCounter {.guard: dummyLock.}: int
|
var atomicCounter {.guard: dummyLock.}: int
|
||||||
|
|
||||||
template atomicRead(x): expr =
|
template atomicRead(x): expr =
|
||||||
{.locks: [dummyLock].}:
|
{.locks: [dummyLock].}:
|
||||||
memoryReadBarrier()
|
memoryReadBarrier()
|
||||||
|
|
@ -135,30 +135,30 @@ Lock levels are used to enforce a global locking order in order to prevent
|
||||||
deadlocks at compile-time. A lock level is an constant integer in the range
|
deadlocks at compile-time. A lock level is an constant integer in the range
|
||||||
0..1_000. Lock level 0 means that no lock is acquired at all.
|
0..1_000. Lock level 0 means that no lock is acquired at all.
|
||||||
|
|
||||||
If a section of code holds a lock of level ``M`` than it can also acquire any
|
If a section of code holds a lock of level ``M`` than it can also acquire any
|
||||||
lock of level ``N < M``. Another lock of level ``M`` cannot be acquired. Locks
|
lock of level ``N < M``. Another lock of level ``M`` cannot be acquired. Locks
|
||||||
of the same level can only be acquired *at the same time* within a
|
of the same level can only be acquired *at the same time* within a
|
||||||
single ``locks`` section:
|
single ``locks`` section:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
var a, b: TLock[2]
|
var a, b: TLock[2]
|
||||||
var x: TLock[1]
|
var x: TLock[1]
|
||||||
# invalid locking order: TLock[1] cannot be acquired before TLock[2]:
|
# invalid locking order: TLock[1] cannot be acquired before TLock[2]:
|
||||||
{.locks: [x].}:
|
{.locks: [x].}:
|
||||||
{.locks: [a].}:
|
{.locks: [a].}:
|
||||||
...
|
...
|
||||||
# valid locking order: TLock[2] acquired before TLock[1]:
|
# valid locking order: TLock[2] acquired before TLock[1]:
|
||||||
{.locks: [a].}:
|
{.locks: [a].}:
|
||||||
{.locks: [x].}:
|
{.locks: [x].}:
|
||||||
...
|
...
|
||||||
|
|
||||||
# invalid locking order: TLock[2] acquired before TLock[2]:
|
# invalid locking order: TLock[2] acquired before TLock[2]:
|
||||||
{.locks: [a].}:
|
{.locks: [a].}:
|
||||||
{.locks: [b].}:
|
{.locks: [b].}:
|
||||||
...
|
...
|
||||||
|
|
||||||
# valid locking order, locks of the same level acquired at the same time:
|
# valid locking order, locks of the same level acquired at the same time:
|
||||||
{.locks: [a, b].}:
|
{.locks: [a, b].}:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -187,7 +187,7 @@ level. This then means that the routine may acquire locks of up to this level.
|
||||||
This is essential so that procs can be called within a ``locks`` section:
|
This is essential so that procs can be called within a ``locks`` section:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
proc p() {.locks: 3.} = discard
|
proc p() {.locks: 3.} = discard
|
||||||
|
|
||||||
var a: TLock[4]
|
var a: TLock[4]
|
||||||
{.locks: [a].}:
|
{.locks: [a].}:
|
||||||
|
|
@ -195,6 +195,6 @@ This is essential so that procs can be called within a ``locks`` section:
|
||||||
p()
|
p()
|
||||||
|
|
||||||
|
|
||||||
As usual ``locks`` is an inferred effect and there is a subtype
|
As usual ``locks`` is an inferred effect and there is a subtype
|
||||||
relation: ``proc () {.locks: N.}`` is a subtype of ``proc () {.locks: M.}``
|
relation: ``proc () {.locks: N.}`` is a subtype of ``proc () {.locks: M.}``
|
||||||
iff (M <= N).
|
iff (M <= N).
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@ A module alias can be introduced via the ``as`` keyword:
|
||||||
|
|
||||||
echo su.format("$1", "lalelu")
|
echo su.format("$1", "lalelu")
|
||||||
|
|
||||||
The original module name is then not accessible. The
|
The original module name is then not accessible. The
|
||||||
notations ``path/to/module`` or ``path.to.module`` or ``"path/to/module"``
|
notations ``path/to/module`` or ``path.to.module`` or ``"path/to/module"``
|
||||||
can be used to refer to a module in subdirectories:
|
can be used to refer to a module in subdirectories:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -104,7 +104,7 @@ Likewise the following does not make sense as the name is ``strutils`` already:
|
||||||
From import statement
|
From import statement
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
After the ``from`` statement a module name follows followed by
|
After the ``from`` statement a module name follows followed by
|
||||||
an ``import`` to list the symbols one likes to use without explict
|
an ``import`` to list the symbols one likes to use without explict
|
||||||
full qualification:
|
full qualification:
|
||||||
|
|
||||||
|
|
@ -115,8 +115,8 @@ full qualification:
|
||||||
# always possible: full qualification:
|
# always possible: full qualification:
|
||||||
echo strutils.replace("abc", "a", "z")
|
echo strutils.replace("abc", "a", "z")
|
||||||
|
|
||||||
It's also possible to use ``from module import nil`` if one wants to import
|
It's also possible to use ``from module import nil`` if one wants to import
|
||||||
the module but wants to enforce fully qualified access to every symbol
|
the module but wants to enforce fully qualified access to every symbol
|
||||||
in ``module``.
|
in ``module``.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -134,15 +134,15 @@ modules don't need to import a module's dependencies:
|
||||||
# module A
|
# module A
|
||||||
import B
|
import B
|
||||||
export B.MyObject
|
export B.MyObject
|
||||||
|
|
||||||
proc `$`*(x: MyObject): string = "my object"
|
proc `$`*(x: MyObject): string = "my object"
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
# module C
|
# module C
|
||||||
import A
|
import A
|
||||||
|
|
||||||
# B.MyObject has been imported implicitly here:
|
# B.MyObject has been imported implicitly here:
|
||||||
var x: MyObject
|
var x: MyObject
|
||||||
echo($x)
|
echo($x)
|
||||||
|
|
||||||
|
|
@ -185,7 +185,7 @@ following places:
|
||||||
Module scope
|
Module scope
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
All identifiers of a module are valid from the point of declaration until
|
All identifiers of a module are valid from the point of declaration until
|
||||||
the end of the module. Identifiers from indirectly dependent modules are *not*
|
the end of the module. Identifiers from indirectly dependent modules are *not*
|
||||||
available. The `system`:idx: module is automatically imported in every module.
|
available. The `system`:idx: module is automatically imported in every module.
|
||||||
|
|
||||||
If a module imports an identifier by two different modules, each occurrence of
|
If a module imports an identifier by two different modules, each occurrence of
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ current module:
|
||||||
Method call syntax
|
Method call syntax
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
For object oriented programming, the syntax ``obj.method(args)`` can be used
|
For object oriented programming, the syntax ``obj.method(args)`` can be used
|
||||||
instead of ``method(obj, args)``. The parentheses can be omitted if there are no
|
instead of ``method(obj, args)``. The parentheses can be omitted if there are no
|
||||||
remaining arguments: ``obj.len`` (instead of ``len(obj)``).
|
remaining arguments: ``obj.len`` (instead of ``len(obj)``).
|
||||||
|
|
||||||
|
|
@ -128,7 +128,7 @@ This method call syntax is not restricted to objects, it can be used
|
||||||
to supply any type of first argument for procedures:
|
to supply any type of first argument for procedures:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
echo("abc".len) # is the same as echo(len("abc"))
|
echo("abc".len) # is the same as echo(len("abc"))
|
||||||
echo("abc".toUpper())
|
echo("abc".toUpper())
|
||||||
echo({'a', 'b', 'c'}.card)
|
echo({'a', 'b', 'c'}.card)
|
||||||
|
|
@ -143,11 +143,11 @@ See also: `Limitations of the method call syntax`_.
|
||||||
Properties
|
Properties
|
||||||
----------
|
----------
|
||||||
Nim has no need for *get-properties*: Ordinary get-procedures that are called
|
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
|
with the *method call syntax* achieve the same. But setting a value is
|
||||||
different; for this a special setter syntax is needed:
|
different; for this a special setter syntax is needed:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
type
|
type
|
||||||
Socket* = ref object of RootObj
|
Socket* = ref object of RootObj
|
||||||
FHost: int # cannot be accessed from the outside of the module
|
FHost: int # cannot be accessed from the outside of the module
|
||||||
|
|
@ -157,7 +157,7 @@ different; for this a special setter syntax is needed:
|
||||||
proc `host=`*(s: var Socket, value: int) {.inline.} =
|
proc `host=`*(s: var Socket, value: int) {.inline.} =
|
||||||
## setter of hostAddr
|
## setter of hostAddr
|
||||||
s.FHost = value
|
s.FHost = value
|
||||||
|
|
||||||
proc host*(s: Socket): int {.inline.} =
|
proc host*(s: Socket): int {.inline.} =
|
||||||
## getter of hostAddr
|
## getter of hostAddr
|
||||||
s.FHost
|
s.FHost
|
||||||
|
|
@ -180,18 +180,18 @@ more argument in this case:
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
proc optarg(x: int, y: int = 0): int = x + y
|
proc optarg(x: int, y: int = 0): int = x + y
|
||||||
proc singlearg(x: int): int = 20*x
|
proc singlearg(x: int): int = 20*x
|
||||||
|
|
||||||
echo optarg 1, " ", singlearg 2 # prints "1 40"
|
echo optarg 1, " ", singlearg 2 # prints "1 40"
|
||||||
|
|
||||||
let fail = optarg 1, optarg 8 # Wrong. Too many arguments for a command call
|
let fail = optarg 1, optarg 8 # Wrong. Too many arguments for a command call
|
||||||
let x = optarg(1, optarg 8) # traditional procedure call with 2 arguments
|
let x = optarg(1, optarg 8) # traditional procedure call with 2 arguments
|
||||||
let y = 1.optarg optarg 8 # same thing as above, w/o the parenthesis
|
let y = 1.optarg optarg 8 # same thing as above, w/o the parenthesis
|
||||||
assert x == y
|
assert x == y
|
||||||
|
|
||||||
The command invocation syntax also can't have complex expressions as arguments.
|
The command invocation syntax also can't have complex expressions as arguments.
|
||||||
For example: (`anonymous procs`_), ``if``, ``case`` or ``try``. The (`do
|
For example: (`anonymous procs`_), ``if``, ``case`` or ``try``. The (`do
|
||||||
notation`_) is limited, but usable for a single proc (see the example in the
|
notation`_) is limited, but usable for a single proc (see the example in the
|
||||||
corresponding section). Function calls with no arguments still needs () to
|
corresponding section). Function calls with no arguments still needs () to
|
||||||
distinguish between a call and the function itself as a first class value.
|
distinguish between a call and the function itself as a first class value.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -221,7 +221,7 @@ the proc's name.
|
||||||
cmp(x.len, y.len))
|
cmp(x.len, y.len))
|
||||||
|
|
||||||
|
|
||||||
Procs as expressions can appear both as nested procs and inside top level
|
Procs as expressions can appear both as nested procs and inside top level
|
||||||
executable code.
|
executable code.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -237,10 +237,10 @@ calls can use the ``do`` keyword:
|
||||||
sort(cities) do (x,y: string) -> int:
|
sort(cities) do (x,y: string) -> int:
|
||||||
cmp(x.len, y.len)
|
cmp(x.len, y.len)
|
||||||
# Less parenthesis using the method plus command syntax:
|
# Less parenthesis using the method plus command syntax:
|
||||||
cities = cities.map do (x:string) -> string:
|
cities = cities.map do (x:string) -> string:
|
||||||
"City of " & x
|
"City of " & x
|
||||||
|
|
||||||
``do`` is written after the parentheses enclosing the regular proc params.
|
``do`` is written after the parentheses enclosing the regular proc params.
|
||||||
The proc expression represented by the do block is appended to them.
|
The proc expression represented by the do block is appended to them.
|
||||||
|
|
||||||
More than one ``do`` block can appear in a single call:
|
More than one ``do`` block can appear in a single call:
|
||||||
|
|
@ -261,11 +261,11 @@ Nonoverloadable builtins
|
||||||
The following builtin procs cannot be overloaded for reasons of implementation
|
The following builtin procs cannot be overloaded for reasons of implementation
|
||||||
simplicity (they require specialized semantic checking)::
|
simplicity (they require specialized semantic checking)::
|
||||||
|
|
||||||
declared, defined, definedInScope, compiles, low, high, sizeOf,
|
declared, defined, definedInScope, compiles, low, high, sizeOf,
|
||||||
is, of, shallowCopy, getAst, astToStr, spawn, procCall
|
is, of, shallowCopy, getAst, astToStr, spawn, procCall
|
||||||
|
|
||||||
Thus they act more like keywords than like ordinary identifiers; unlike a
|
Thus they act more like keywords than like ordinary identifiers; unlike a
|
||||||
keyword however, a redefinition may `shadow`:idx: the definition in
|
keyword however, a redefinition may `shadow`:idx: the definition in
|
||||||
the ``system`` module. From this list the following should not be written in dot
|
the ``system`` module. From this list the following should not be written in dot
|
||||||
notation ``x.f`` since ``x`` cannot be type checked before it gets passed
|
notation ``x.f`` since ``x`` cannot be type checked before it gets passed
|
||||||
to ``f``::
|
to ``f``::
|
||||||
|
|
@ -342,11 +342,11 @@ returned value is an l-value and can be modified by the caller:
|
||||||
|
|
||||||
proc WriteAccessToG(): var int =
|
proc WriteAccessToG(): var int =
|
||||||
result = g
|
result = g
|
||||||
|
|
||||||
WriteAccessToG() = 6
|
WriteAccessToG() = 6
|
||||||
assert g == 6
|
assert g == 6
|
||||||
|
|
||||||
It is a compile time error if the implicitly introduced pointer could be
|
It is a compile time error if the implicitly introduced pointer could be
|
||||||
used to access a location beyond its lifetime:
|
used to access a location beyond its lifetime:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -354,7 +354,7 @@ used to access a location beyond its lifetime:
|
||||||
var g = 0
|
var g = 0
|
||||||
result = g # Error!
|
result = g # Error!
|
||||||
|
|
||||||
For iterators, a component of a tuple return type can have a ``var`` type too:
|
For iterators, a component of a tuple return type can have a ``var`` type too:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
iterator mpairs(a: var seq[string]): tuple[key: int, val: var string] =
|
iterator mpairs(a: var seq[string]): tuple[key: int, val: var string] =
|
||||||
|
|
@ -384,28 +384,28 @@ dispatch.
|
||||||
x: int
|
x: int
|
||||||
PlusExpr = ref object of Expression
|
PlusExpr = ref object of Expression
|
||||||
a, b: Expression
|
a, b: Expression
|
||||||
|
|
||||||
method eval(e: Expression): int =
|
method eval(e: Expression): int =
|
||||||
# override this base method
|
# override this base method
|
||||||
quit "to override!"
|
quit "to override!"
|
||||||
|
|
||||||
method eval(e: Literal): int = return e.x
|
method eval(e: Literal): int = return e.x
|
||||||
|
|
||||||
method eval(e: PlusExpr): int =
|
method eval(e: PlusExpr): int =
|
||||||
# watch out: relies on dynamic binding
|
# watch out: relies on dynamic binding
|
||||||
result = eval(e.a) + eval(e.b)
|
result = eval(e.a) + eval(e.b)
|
||||||
|
|
||||||
proc newLit(x: int): Literal =
|
proc newLit(x: int): Literal =
|
||||||
new(result)
|
new(result)
|
||||||
result.x = x
|
result.x = x
|
||||||
|
|
||||||
proc newPlus(a, b: Expression): PlusExpr =
|
proc newPlus(a, b: Expression): PlusExpr =
|
||||||
new(result)
|
new(result)
|
||||||
result.a = a
|
result.a = a
|
||||||
result.b = b
|
result.b = b
|
||||||
|
|
||||||
echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
|
echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
|
||||||
|
|
||||||
In the example the constructors ``newLit`` and ``newPlus`` are procs
|
In the example the constructors ``newLit`` and ``newPlus`` are procs
|
||||||
because they should use static binding, but ``eval`` is a method because it
|
because they should use static binding, but ``eval`` is a method because it
|
||||||
requires dynamic binding.
|
requires dynamic binding.
|
||||||
|
|
@ -418,24 +418,24 @@ dispatching:
|
||||||
Thing = ref object of RootObj
|
Thing = ref object of RootObj
|
||||||
Unit = ref object of Thing
|
Unit = ref object of Thing
|
||||||
x: int
|
x: int
|
||||||
|
|
||||||
method collide(a, b: Thing) {.inline.} =
|
method collide(a, b: Thing) {.inline.} =
|
||||||
quit "to override!"
|
quit "to override!"
|
||||||
|
|
||||||
method collide(a: Thing, b: Unit) {.inline.} =
|
method collide(a: Thing, b: Unit) {.inline.} =
|
||||||
echo "1"
|
echo "1"
|
||||||
|
|
||||||
method collide(a: Unit, b: Thing) {.inline.} =
|
method collide(a: Unit, b: Thing) {.inline.} =
|
||||||
echo "2"
|
echo "2"
|
||||||
|
|
||||||
var a, b: Unit
|
var a, b: Unit
|
||||||
new a
|
new a
|
||||||
new b
|
new b
|
||||||
collide(a, b) # output: 2
|
collide(a, b) # output: 2
|
||||||
|
|
||||||
|
|
||||||
Invocation of a multi-method cannot be ambiguous: collide 2 is preferred 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 ``Unit, Thing`` is preferred over ``Thing, Unit``.
|
In the example ``Unit, Thing`` is preferred over ``Thing, Unit``.
|
||||||
|
|
||||||
**Performance note**: Nim does not produce a virtual method table, but
|
**Performance note**: Nim does not produce a virtual method table, but
|
||||||
|
|
@ -450,7 +450,7 @@ Iterators and the for statement
|
||||||
The `for`:idx: statement is an abstract mechanism to iterate over the elements
|
The `for`:idx: statement is an abstract mechanism to iterate over the elements
|
||||||
of a container. It relies on an `iterator`:idx: to do so. Like ``while``
|
of a container. It relies on an `iterator`:idx: to do so. Like ``while``
|
||||||
statements, ``for`` statements open an `implicit block`:idx:, so that they
|
statements, ``for`` statements open an `implicit block`:idx:, so that they
|
||||||
can be left with a ``break`` statement.
|
can be left with a ``break`` statement.
|
||||||
|
|
||||||
The ``for`` loop declares iteration variables - their scope reaches until the
|
The ``for`` loop declares iteration variables - their scope reaches until the
|
||||||
end of the loop body. The iteration variables' types are inferred by the
|
end of the loop body. The iteration variables' types are inferred by the
|
||||||
|
|
@ -486,7 +486,7 @@ The compiler generates code as if the programmer would have written this:
|
||||||
|
|
||||||
If the iterator yields a tuple, there can be as many iteration variables
|
If the iterator yields a tuple, there can be as many iteration variables
|
||||||
as there are components in the tuple. The i'th iteration variable's type is
|
as there are components in the tuple. The i'th iteration variable's type is
|
||||||
the type of the i'th component. In other words, implicit tuple unpacking in a
|
the type of the i'th component. In other words, implicit tuple unpacking in a
|
||||||
for loop context is supported.
|
for loop context is supported.
|
||||||
|
|
||||||
Implict items/pairs invocations
|
Implict items/pairs invocations
|
||||||
|
|
@ -498,11 +498,11 @@ ie. an ``items`` iterator is implicitly invoked:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
for x in [1,2,3]: echo x
|
for x in [1,2,3]: echo x
|
||||||
|
|
||||||
If the for loop has exactly 2 variables, a ``pairs`` iterator is implicitly
|
If the for loop has exactly 2 variables, a ``pairs`` iterator is implicitly
|
||||||
invoked.
|
invoked.
|
||||||
|
|
||||||
Symbol lookup of the identifiers ``items``/``pairs`` is performed after
|
Symbol lookup of the identifiers ``items``/``pairs`` is performed after
|
||||||
the rewriting step, so that all overloads of ``items``/``pairs`` are taken
|
the rewriting step, so that all overloads of ``items``/``pairs`` are taken
|
||||||
into account.
|
into account.
|
||||||
|
|
||||||
|
|
@ -511,7 +511,7 @@ First class iterators
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
There are 2 kinds of iterators in Nim: *inline* and *closure* iterators.
|
There are 2 kinds of iterators in Nim: *inline* and *closure* iterators.
|
||||||
An `inline iterator`:idx: is an iterator that's always inlined by the compiler
|
An `inline iterator`:idx: is an iterator that's always inlined by the compiler
|
||||||
leading to zero overhead for the abstraction, but may result in a heavy
|
leading to zero overhead for the abstraction, but may result in a heavy
|
||||||
increase in code size. Inline iterators are second class citizens;
|
increase in code size. Inline iterators are second class citizens;
|
||||||
They can be passed as parameters only to other inlining code facilities like
|
They can be passed as parameters only to other inlining code facilities like
|
||||||
|
|
@ -522,7 +522,7 @@ In contrast to that, a `closure iterator`:idx: can be passed around more freely:
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
iterator count0(): int {.closure.} =
|
iterator count0(): int {.closure.} =
|
||||||
yield 0
|
yield 0
|
||||||
|
|
||||||
iterator count2(): int {.closure.} =
|
iterator count2(): int {.closure.} =
|
||||||
var x = 1
|
var x = 1
|
||||||
yield x
|
yield x
|
||||||
|
|
@ -539,7 +539,7 @@ Closure iterators have other restrictions than inline iterators:
|
||||||
|
|
||||||
1. ``yield`` in a closure iterator can not occur in a ``try`` statement.
|
1. ``yield`` in a closure iterator can not occur in a ``try`` statement.
|
||||||
2. For now, a closure iterator cannot be evaluated at compile time.
|
2. For now, a closure iterator cannot be evaluated at compile time.
|
||||||
3. ``return`` is allowed in a closure iterator (but rarely useful) and ends
|
3. ``return`` is allowed in a closure iterator (but rarely useful) and ends
|
||||||
iteration.
|
iteration.
|
||||||
4. Neither inline nor closure iterators can be recursive.
|
4. Neither inline nor closure iterators can be recursive.
|
||||||
|
|
||||||
|
|
@ -547,7 +547,7 @@ Iterators that are neither marked ``{.closure.}`` nor ``{.inline.}`` explicitly
|
||||||
default to being inline, but this may change in future versions of the
|
default to being inline, but this may change in future versions of the
|
||||||
implementation.
|
implementation.
|
||||||
|
|
||||||
The ``iterator`` type is always of the calling convention ``closure``
|
The ``iterator`` type is always of the calling convention ``closure``
|
||||||
implicitly; the following example shows how to use iterators to implement
|
implicitly; the following example shows how to use iterators to implement
|
||||||
a `collaborative tasking`:idx: system:
|
a `collaborative tasking`:idx: system:
|
||||||
|
|
||||||
|
|
@ -650,7 +650,7 @@ parameters of an outer factory proc:
|
||||||
Converters
|
Converters
|
||||||
==========
|
==========
|
||||||
|
|
||||||
A converter is like an ordinary proc except that it enhances
|
A converter is like an ordinary proc except that it enhances
|
||||||
the "implicitly convertible" type relation (see `Convertible relation`_):
|
the "implicitly convertible" type relation (see `Convertible relation`_):
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ templates and macros), depending on the desired effect:
|
||||||
The following dot operators are available:
|
The following dot operators are available:
|
||||||
|
|
||||||
operator `.`
|
operator `.`
|
||||||
------------
|
------------
|
||||||
This operator will be matched against both field accesses and method calls.
|
This operator will be matched against both field accesses and method calls.
|
||||||
|
|
||||||
operator `.()`
|
operator `.()`
|
||||||
|
|
|
||||||
|
|
@ -176,8 +176,8 @@ The rules for compile-time computability are:
|
||||||
1. Literals are compile-time computable.
|
1. Literals are compile-time computable.
|
||||||
2. Type conversions are compile-time computable.
|
2. Type conversions are compile-time computable.
|
||||||
3. Procedure calls of the form ``p(X)`` are compile-time computable if
|
3. Procedure calls of the form ``p(X)`` are compile-time computable if
|
||||||
``p`` is a proc without side-effects (see the `noSideEffect pragma
|
``p`` is a proc without side-effects (see the `noSideEffect pragma
|
||||||
<#pragmas-nosideeffect-pragma>`_ for details) and if ``X`` is a
|
<#pragmas-nosideeffect-pragma>`_ for details) and if ``X`` is a
|
||||||
(possibly empty) list of compile-time computable arguments.
|
(possibly empty) list of compile-time computable arguments.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
Taint mode
|
Taint mode
|
||||||
==========
|
==========
|
||||||
|
|
||||||
The Nim compiler and most parts of the standard library support
|
The Nim compiler and most parts of the standard library support
|
||||||
a taint mode. Input strings are declared with the `TaintedString`:idx:
|
a taint mode. Input strings are declared with the `TaintedString`:idx:
|
||||||
string type declared in the ``system`` module.
|
string type declared in the ``system`` module.
|
||||||
|
|
||||||
If the taint mode is turned on (via the ``--taintMode:on`` command line
|
If the taint mode is turned on (via the ``--taintMode:on`` command line
|
||||||
option) it is a distinct string type which helps to detect input
|
option) it is a distinct string type which helps to detect input
|
||||||
validation errors:
|
validation errors:
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@ validation errors:
|
||||||
echo "your name: "
|
echo "your name: "
|
||||||
var name: TaintedString = stdin.readline
|
var name: TaintedString = stdin.readline
|
||||||
# it is safe here to output the name without any input validation, so
|
# it is safe here to output the name without any input validation, so
|
||||||
# we simply convert `name` to string to make the compiler happy:
|
# we simply convert `name` to string to make the compiler happy:
|
||||||
echo "hi, ", name.string
|
echo "hi, ", name.string
|
||||||
|
|
||||||
If the taint mode is turned off, ``TaintedString`` is simply an alias for
|
If the taint mode is turned off, ``TaintedString`` is simply an alias for
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,17 @@ 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:
|
templates:
|
||||||
|
|
||||||
| ``a > b`` is transformed into ``b < a``.
|
| ``a > b`` is transformed into ``b < a``.
|
||||||
| ``a in b`` is transformed into ``contains(b, a)``.
|
| ``a in b`` is transformed into ``contains(b, a)``.
|
||||||
| ``notin`` and ``isnot`` have the obvious meanings.
|
| ``notin`` and ``isnot`` have the obvious meanings.
|
||||||
|
|
||||||
The "types" of templates can be the symbols ``expr`` (stands for *expression*),
|
The "types" of templates can be the symbols ``expr`` (stands for *expression*),
|
||||||
``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type
|
``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type
|
||||||
description*). These are "meta types", they can only be used in certain
|
description*). These are "meta types", they can only be used in certain
|
||||||
contexts. Real types can be used too; this implies that expressions are
|
contexts. Real types can be used too; this implies that expressions are
|
||||||
expected.
|
expected.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ So ordinary templates cannot receive undeclared identifiers:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
template declareInt(x: expr) =
|
template declareInt(x: expr) =
|
||||||
var x: int
|
var x: int
|
||||||
|
|
||||||
declareInt(x) # error: unknown identifier: 'x'
|
declareInt(x) # error: unknown identifier: 'x'
|
||||||
|
|
@ -51,7 +51,7 @@ receive undeclared identifiers:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
template declareInt(x: expr) {.immediate.} =
|
template declareInt(x: expr) {.immediate.} =
|
||||||
var x: int
|
var x: int
|
||||||
|
|
||||||
declareInt(x) # valid
|
declareInt(x) # valid
|
||||||
|
|
@ -75,11 +75,11 @@ special ``:`` syntax:
|
||||||
close(f)
|
close(f)
|
||||||
else:
|
else:
|
||||||
quit("cannot open: " & fn)
|
quit("cannot open: " & fn)
|
||||||
|
|
||||||
withFile(txt, "ttempl3.txt", fmWrite):
|
withFile(txt, "ttempl3.txt", fmWrite):
|
||||||
txt.writeLine("line 1")
|
txt.writeLine("line 1")
|
||||||
txt.writeLine("line 2")
|
txt.writeLine("line 2")
|
||||||
|
|
||||||
In the example the two ``writeLine`` statements are bound to the ``actions``
|
In the example the two ``writeLine`` statements are bound to the ``actions``
|
||||||
parameter.
|
parameter.
|
||||||
|
|
||||||
|
|
@ -92,9 +92,9 @@ bound from the definition scope of the template:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
# Module A
|
# Module A
|
||||||
var
|
var
|
||||||
lastId = 0
|
lastId = 0
|
||||||
|
|
||||||
template genId*: expr =
|
template genId*: expr =
|
||||||
inc(lastId)
|
inc(lastId)
|
||||||
lastId
|
lastId
|
||||||
|
|
@ -102,10 +102,10 @@ bound from the definition scope of the template:
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
# Module B
|
# Module B
|
||||||
import A
|
import A
|
||||||
|
|
||||||
echo genId() # Works as 'lastId' has been bound in 'genId's defining scope
|
echo genId() # Works as 'lastId' has been bound in 'genId's defining scope
|
||||||
|
|
||||||
As in generics symbol binding can be influenced via ``mixin`` or ``bind``
|
As in generics symbol binding can be influenced via ``mixin`` or ``bind``
|
||||||
statements.
|
statements.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -117,11 +117,11 @@ In templates identifiers can be constructed with the backticks notation:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
template typedef(name: expr, typ: typedesc) {.immediate.} =
|
template typedef(name: expr, typ: typedesc) {.immediate.} =
|
||||||
type
|
type
|
||||||
`T name`* {.inject.} = typ
|
`T name`* {.inject.} = typ
|
||||||
`P name`* {.inject.} = ref `T name`
|
`P name`* {.inject.} = ref `T name`
|
||||||
|
|
||||||
typedef(myint, int)
|
typedef(myint, int)
|
||||||
var x: PMyInt
|
var x: PMyInt
|
||||||
|
|
||||||
|
|
@ -150,7 +150,7 @@ shadowed by the same argument name even when fully qualified:
|
||||||
|
|
||||||
tstLev(levA)
|
tstLev(levA)
|
||||||
# produces: 'levA levA'
|
# produces: 'levA levA'
|
||||||
|
|
||||||
But the global symbol can properly be captured by a ``bind`` statement:
|
But the global symbol can properly be captured by a ``bind`` statement:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -177,14 +177,14 @@ Per default templates are `hygienic`:idx:\: Local identifiers declared in a
|
||||||
template cannot be accessed in the instantiation context:
|
template cannot be accessed in the instantiation context:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
template newException*(exceptn: typedesc, message: string): expr =
|
template newException*(exceptn: typedesc, message: string): expr =
|
||||||
var
|
var
|
||||||
e: ref exceptn # e is implicitly gensym'ed here
|
e: ref exceptn # e is implicitly gensym'ed here
|
||||||
new(e)
|
new(e)
|
||||||
e.msg = message
|
e.msg = message
|
||||||
e
|
e
|
||||||
|
|
||||||
# so this works:
|
# so this works:
|
||||||
let e = "message"
|
let e = "message"
|
||||||
raise newException(EIO, e)
|
raise newException(EIO, e)
|
||||||
|
|
@ -196,7 +196,7 @@ symbols are not exposed but inject'ed are.
|
||||||
|
|
||||||
The default for symbols of entity ``type``, ``var``, ``let`` and ``const``
|
The default for symbols of entity ``type``, ``var``, ``let`` and ``const``
|
||||||
is ``gensym`` and for ``proc``, ``iterator``, ``converter``, ``template``,
|
is ``gensym`` and for ``proc``, ``iterator``, ``converter``, ``template``,
|
||||||
``macro`` is ``inject``. However, if the name of the entity is passed as a
|
``macro`` is ``inject``. However, if the name of the entity is passed as a
|
||||||
template parameter, it is an inject'ed symbol:
|
template parameter, it is an inject'ed symbol:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -204,7 +204,7 @@ template parameter, it is an inject'ed symbol:
|
||||||
block:
|
block:
|
||||||
var f: File # since 'f' is a template param, it's injected implicitly
|
var f: File # since 'f' is a template param, it's injected implicitly
|
||||||
...
|
...
|
||||||
|
|
||||||
withFile(txt, "ttempl3.txt", fmWrite):
|
withFile(txt, "ttempl3.txt", fmWrite):
|
||||||
txt.writeLine("line 1")
|
txt.writeLine("line 1")
|
||||||
txt.writeLine("line 2")
|
txt.writeLine("line 2")
|
||||||
|
|
@ -215,7 +215,7 @@ no semantics outside of a template definition and cannot be abstracted over:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
{.pragma myInject: inject.}
|
{.pragma myInject: inject.}
|
||||||
|
|
||||||
template t() =
|
template t() =
|
||||||
var x {.myInject.}: int # does NOT work
|
var x {.myInject.}: int # does NOT work
|
||||||
|
|
||||||
|
|
@ -334,9 +334,9 @@ BindSym
|
||||||
-------
|
-------
|
||||||
|
|
||||||
The above ``debug`` macro relies on the fact that ``write``, ``writeLine`` and
|
The above ``debug`` macro relies on the fact that ``write``, ``writeLine`` and
|
||||||
``stdout`` are declared in the system module and thus visible in the
|
``stdout`` are declared in the system module and thus visible in the
|
||||||
instantiating context. There is a way to use bound identifiers
|
instantiating context. There is a way to use bound identifiers
|
||||||
(aka `symbols`:idx:) instead of using unbound identifiers. The ``bindSym``
|
(aka `symbols`:idx:) instead of using unbound identifiers. The ``bindSym``
|
||||||
builtin can be used for that:
|
builtin can be used for that:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -418,8 +418,8 @@ powerful programming construct that still suffices. So the "check list" is:
|
||||||
Macros as pragmas
|
Macros as pragmas
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Whole routines (procs, iterators etc.) can also be passed to a template or
|
Whole routines (procs, iterators etc.) can also be passed to a template or
|
||||||
a macro via the pragma notation:
|
a macro via the pragma notation:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
template m(s: stmt) = discard
|
template m(s: stmt) = discard
|
||||||
|
|
|
||||||
|
|
@ -3,32 +3,32 @@ Term rewriting macros
|
||||||
|
|
||||||
Term rewriting macros are macros or templates that have not only
|
Term rewriting macros are macros or templates that have not only
|
||||||
a *name* but also a *pattern* that is searched for after the semantic checking
|
a *name* but also a *pattern* that is searched for after the semantic checking
|
||||||
phase of the compiler: This means they provide an easy way to enhance the
|
phase of the compiler: This means they provide an easy way to enhance the
|
||||||
compilation pipeline with user defined optimizations:
|
compilation pipeline with user defined optimizations:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
template optMul{`*`(a, 2)}(a: int): int = a+a
|
template optMul{`*`(a, 2)}(a: int): int = a+a
|
||||||
|
|
||||||
let x = 3
|
let x = 3
|
||||||
echo x * 2
|
echo x * 2
|
||||||
|
|
||||||
The compiler now rewrites ``x * 2`` as ``x + x``. The code inside the
|
The compiler now rewrites ``x * 2`` as ``x + x``. The code inside the
|
||||||
curlies is the pattern to match against. The operators ``*``, ``**``,
|
curlies is the pattern to match against. The operators ``*``, ``**``,
|
||||||
``|``, ``~`` have a special meaning in patterns if they are written in infix
|
``|``, ``~`` have a special meaning in patterns if they are written in infix
|
||||||
notation, so to match verbatim against ``*`` the ordinary function call syntax
|
notation, so to match verbatim against ``*`` the ordinary function call syntax
|
||||||
needs to be used.
|
needs to be used.
|
||||||
|
|
||||||
|
|
||||||
Unfortunately optimizations are hard to get right and even the tiny example
|
Unfortunately optimizations are hard to get right and even the tiny example
|
||||||
is **wrong**:
|
is **wrong**:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
template optMul{`*`(a, 2)}(a: int): int = a+a
|
template optMul{`*`(a, 2)}(a: int): int = a+a
|
||||||
|
|
||||||
proc f(): int =
|
proc f(): int =
|
||||||
echo "side effect!"
|
echo "side effect!"
|
||||||
result = 55
|
result = 55
|
||||||
|
|
||||||
echo f() * 2
|
echo f() * 2
|
||||||
|
|
||||||
We cannot duplicate 'a' if it denotes an expression that has a side effect!
|
We cannot duplicate 'a' if it denotes an expression that has a side effect!
|
||||||
|
|
@ -36,11 +36,11 @@ Fortunately Nim supports side effect analysis:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
template optMul{`*`(a, 2)}(a: int{noSideEffect}): int = a+a
|
template optMul{`*`(a, 2)}(a: int{noSideEffect}): int = a+a
|
||||||
|
|
||||||
proc f(): int =
|
proc f(): int =
|
||||||
echo "side effect!"
|
echo "side effect!"
|
||||||
result = 55
|
result = 55
|
||||||
|
|
||||||
echo f() * 2 # not optimized ;-)
|
echo f() * 2 # not optimized ;-)
|
||||||
|
|
||||||
You can make one overload matching with a constraint and one without, and the
|
You can make one overload matching with a constraint and one without, and the
|
||||||
|
|
@ -53,13 +53,13 @@ blindly:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
template mulIsCommutative{`*`(a, b)}(a, b: int): int = b*a
|
template mulIsCommutative{`*`(a, b)}(a, b: int): int = b*a
|
||||||
|
|
||||||
What optimizers really need to do is a *canonicalization*:
|
What optimizers really need to do is a *canonicalization*:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
template canonMul{`*`(a, b)}(a: int{lit}, b: int): int = b*a
|
template canonMul{`*`(a, b)}(a: int{lit}, b: int): int = b*a
|
||||||
|
|
||||||
The ``int{lit}`` parameter pattern matches against an expression of
|
The ``int{lit}`` parameter pattern matches against an expression of
|
||||||
type ``int``, but only if it's a literal.
|
type ``int``, but only if it's a literal.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ type ``int``, but only if it's a literal.
|
||||||
Parameter constraints
|
Parameter constraints
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
The `parameter constraint`:idx: expression can use the operators ``|`` (or),
|
The `parameter constraint`:idx: expression can use the operators ``|`` (or),
|
||||||
``&`` (and) and ``~`` (not) and the following predicates:
|
``&`` (and) and ``~`` (not) and the following predicates:
|
||||||
|
|
||||||
=================== =====================================================
|
=================== =====================================================
|
||||||
|
|
@ -75,7 +75,7 @@ Predicate Meaning
|
||||||
=================== =====================================================
|
=================== =====================================================
|
||||||
``atom`` The matching node has no children.
|
``atom`` The matching node has no children.
|
||||||
``lit`` The matching node is a literal like "abc", 12.
|
``lit`` The matching node is a literal like "abc", 12.
|
||||||
``sym`` The matching node must be a symbol (a bound
|
``sym`` The matching node must be a symbol (a bound
|
||||||
identifier).
|
identifier).
|
||||||
``ident`` The matching node must be an identifier (an unbound
|
``ident`` The matching node must be an identifier (an unbound
|
||||||
identifier).
|
identifier).
|
||||||
|
|
@ -101,15 +101,15 @@ Predicate Meaning
|
||||||
``enumfield`` A symbol which is a field in an enumeration.
|
``enumfield`` A symbol which is a field in an enumeration.
|
||||||
``forvar`` A for loop variable.
|
``forvar`` A for loop variable.
|
||||||
``label`` A label (used in ``block`` statements).
|
``label`` A label (used in ``block`` statements).
|
||||||
``nk*`` The matching AST must have the specified kind.
|
``nk*`` The matching AST must have the specified kind.
|
||||||
(Example: ``nkIfStmt`` denotes an ``if`` statement.)
|
(Example: ``nkIfStmt`` denotes an ``if`` statement.)
|
||||||
``alias`` States that the marked parameter needs to alias
|
``alias`` States that the marked parameter needs to alias
|
||||||
with *some* other parameter.
|
with *some* other parameter.
|
||||||
``noalias`` States that *every* other parameter must not alias
|
``noalias`` States that *every* other parameter must not alias
|
||||||
with the marked parameter.
|
with the marked parameter.
|
||||||
=================== =====================================================
|
=================== =====================================================
|
||||||
|
|
||||||
Predicates that share their name with a keyword have to be escaped with
|
Predicates that share their name with a keyword have to be escaped with
|
||||||
backticks: `` `const` ``.
|
backticks: `` `const` ``.
|
||||||
The ``alias`` and ``noalias`` predicates refer not only to the matching AST,
|
The ``alias`` and ``noalias`` predicates refer not only to the matching AST,
|
||||||
but also to every other bound parameter; syntactically they need to occur after
|
but also to every other bound parameter; syntactically they need to occur after
|
||||||
|
|
@ -151,14 +151,14 @@ constant folding, so the following does not work:
|
||||||
The reason is that the compiler already transformed the 1 into "1" for
|
The reason is that the compiler already transformed the 1 into "1" for
|
||||||
the ``echo`` statement. However, a term rewriting macro should not change the
|
the ``echo`` statement. However, a term rewriting macro should not change the
|
||||||
semantics anyway. In fact they can be deactivated with the ``--patterns:off``
|
semantics anyway. In fact they can be deactivated with the ``--patterns:off``
|
||||||
command line option or temporarily with the ``patterns`` pragma.
|
command line option or temporarily with the ``patterns`` pragma.
|
||||||
|
|
||||||
|
|
||||||
The ``{}`` operator
|
The ``{}`` operator
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
A pattern expression can be bound to a pattern parameter via the ``expr{param}``
|
A pattern expression can be bound to a pattern parameter via the ``expr{param}``
|
||||||
notation:
|
notation:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
template t{(0|1|2){x}}(x: expr): expr = x+1
|
template t{(0|1|2){x}}(x: expr): expr = x+1
|
||||||
|
|
@ -176,7 +176,7 @@ The ``~`` operator is the **not** operator in patterns:
|
||||||
template t{x = (~x){y} and (~x){z}}(x, y, z: bool): stmt =
|
template t{x = (~x){y} and (~x){z}}(x, y, z: bool): stmt =
|
||||||
x = y
|
x = y
|
||||||
if x: x = z
|
if x: x = z
|
||||||
|
|
||||||
var
|
var
|
||||||
a = false
|
a = false
|
||||||
b = true
|
b = true
|
||||||
|
|
@ -189,12 +189,12 @@ The ``*`` operator
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The ``*`` operator can *flatten* a nested binary expression like ``a & b & c``
|
The ``*`` operator can *flatten* a nested binary expression like ``a & b & c``
|
||||||
to ``&(a, b, c)``:
|
to ``&(a, b, c)``:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
var
|
var
|
||||||
calls = 0
|
calls = 0
|
||||||
|
|
||||||
proc `&&`(s: varargs[string]): string =
|
proc `&&`(s: varargs[string]): string =
|
||||||
result = s[0]
|
result = s[0]
|
||||||
for i in 1..len(s)-1: result.add s[i]
|
for i in 1..len(s)-1: result.add s[i]
|
||||||
|
|
@ -211,8 +211,8 @@ to ``&(a, b, c)``:
|
||||||
|
|
||||||
The second operator of `*` must be a parameter; it is used to gather all the
|
The second operator of `*` must be a parameter; it is used to gather all the
|
||||||
arguments. The expression ``"my" && (space & "awe" && "some " ) && "concat"``
|
arguments. The expression ``"my" && (space & "awe" && "some " ) && "concat"``
|
||||||
is passed to ``optConc`` in ``a`` as a special list (of kind ``nkArgList``)
|
is passed to ``optConc`` in ``a`` as a special list (of kind ``nkArgList``)
|
||||||
which is flattened into a call expression; thus the invocation of ``optConc``
|
which is flattened into a call expression; thus the invocation of ``optConc``
|
||||||
produces:
|
produces:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -245,7 +245,7 @@ all the arguments, but also the matched operators in reverse polish notation:
|
||||||
|
|
||||||
var x, y, z: Matrix
|
var x, y, z: Matrix
|
||||||
|
|
||||||
echo x + y * z - x
|
echo x + y * z - x
|
||||||
|
|
||||||
This passes the expression ``x + y * z - x`` to the ``optM`` macro as
|
This passes the expression ``x + y * z - x`` to the ``optM`` macro as
|
||||||
an ``nnkArgList`` node containing::
|
an ``nnkArgList`` node containing::
|
||||||
|
|
@ -265,7 +265,7 @@ an ``nnkArgList`` node containing::
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Parameters in a pattern are type checked in the matching process. If a
|
Parameters in a pattern are type checked in the matching process. If a
|
||||||
parameter is of the type ``varargs`` it is treated specially and it can match
|
parameter is of the type ``varargs`` it is treated specially and it can match
|
||||||
0 or more arguments in the AST to be matched against:
|
0 or more arguments in the AST to be matched against:
|
||||||
|
|
||||||
|
|
@ -275,7 +275,7 @@ parameter is of the type ``varargs`` it is treated specially and it can match
|
||||||
((write|writeLine){w})(f, y)
|
((write|writeLine){w})(f, y)
|
||||||
}(x, y: varargs[expr], f: File, w: expr) =
|
}(x, y: varargs[expr], f: File, w: expr) =
|
||||||
w(f, x, y)
|
w(f, x, y)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Example: Partial evaluation
|
Example: Partial evaluation
|
||||||
|
|
@ -310,7 +310,7 @@ The following example shows how some form of hoisting can be implemented:
|
||||||
|
|
||||||
The ``optPeg`` template optimizes the case of a peg constructor with a string
|
The ``optPeg`` template optimizes the case of a peg constructor with a string
|
||||||
literal, so that the pattern will only be parsed once at program startup and
|
literal, so that the pattern will only be parsed once at program startup and
|
||||||
stored in a global ``gl`` which is then re-used. This optimization is called
|
stored in a global ``gl`` which is then re-used. This optimization is called
|
||||||
hoisting because it is comparable to classical loop hoisting.
|
hoisting because it is comparable to classical loop hoisting.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -343,7 +343,7 @@ ordinary routines.
|
||||||
Move optimization
|
Move optimization
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The ``call`` constraint is particularly useful to implement a move
|
The ``call`` constraint is particularly useful to implement a move
|
||||||
optimization for types that have copying semantics:
|
optimization for types that have copying semantics:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,7 @@ matches better than just ``T`` then.
|
||||||
proc sayHi(x: var int): string =
|
proc sayHi(x: var int): string =
|
||||||
# matches a var int
|
# matches a var int
|
||||||
result = $(x + 10)
|
result = $(x + 10)
|
||||||
|
|
||||||
proc sayHello(x: int) =
|
proc sayHello(x: int) =
|
||||||
var m = x # a mutable version of x
|
var m = x # a mutable version of x
|
||||||
echo sayHi(x) # matches the non-var version of sayHi
|
echo sayHi(x) # matches the non-var version of sayHi
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,6 @@ Example:
|
||||||
A type section begins with the ``type`` keyword. It contains multiple
|
A type section begins with the ``type`` keyword. It contains multiple
|
||||||
type definitions. A type definition binds a type to a name. Type definitions
|
type definitions. A type definition binds a type to a name. Type definitions
|
||||||
can be recursive or even mutually recursive. Mutually recursive types are only
|
can be recursive or even mutually recursive. Mutually recursive types are only
|
||||||
possible within a single ``type`` section. Nominal types like ``objects``
|
possible within a single ``type`` section. Nominal types like ``objects``
|
||||||
or ``enums`` can only be defined in a ``type`` section.
|
or ``enums`` can only be defined in a ``type`` section.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ Note that there can be exceptions to these rules. Nim being as flexible as it
|
||||||
is, there will be parts of this style guide that don't make sense in certain
|
is, there will be parts of this style guide that don't make sense in certain
|
||||||
contexts. Furthermore, just as
|
contexts. Furthermore, just as
|
||||||
`Python's style guide<http://legacy.python.org/dev/peps/pep-0008/>`_ changes
|
`Python's style guide<http://legacy.python.org/dev/peps/pep-0008/>`_ changes
|
||||||
over time, this style guide will too.
|
over time, this style guide will too.
|
||||||
|
|
||||||
These rules will only be enforced for contributions to the Nim
|
These rules will only be enforced for contributions to the Nim
|
||||||
codebase and official projects, such as the Nim compiler, the standard library,
|
codebase and official projects, such as the Nim compiler, the standard library,
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
=====================
|
=====================
|
||||||
Nimfix User Guide
|
Nimfix User Guide
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
:Author: Andreas Rumpf
|
:Author: Andreas Rumpf
|
||||||
:Version: |nimversion|
|
:Version: |nimversion|
|
||||||
|
|
||||||
**WARNING**: Nimfix is currently beta-quality.
|
**WARNING**: Nimfix is currently beta-quality.
|
||||||
|
|
||||||
Nimfix is a tool to help you upgrade from Nimrod (<= version 0.9.6) to
|
Nimfix is a tool to help you upgrade from Nimrod (<= version 0.9.6) to
|
||||||
Nim (=> version 0.10.0).
|
Nim (=> version 0.10.0).
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ Options:
|
||||||
--wholeProject overwrite every processed file.
|
--wholeProject overwrite every processed file.
|
||||||
--checkExtern:on|off style check also extern names
|
--checkExtern:on|off style check also extern names
|
||||||
--styleCheck:on|off|auto performs style checking for identifiers
|
--styleCheck:on|off|auto performs style checking for identifiers
|
||||||
and suggests an alternative spelling;
|
and suggests an alternative spelling;
|
||||||
'auto' corrects the spelling.
|
'auto' corrects the spelling.
|
||||||
|
|
||||||
In addition, all command line options of Nim are supported.
|
In addition, all command line options of Nim are supported.
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@
|
||||||
|
|
||||||
|
|
||||||
Nimgrep is a command line tool for search&replace tasks. It can search for
|
Nimgrep is a command line tool for search&replace tasks. It can search for
|
||||||
regex or peg patterns and can search whole directories at once. User
|
regex or peg patterns and can search whole directories at once. User
|
||||||
confirmation for every single replace operation can be requested.
|
confirmation for every single replace operation can be requested.
|
||||||
|
|
||||||
Nimgrep has particularly good support for Nim's
|
Nimgrep has particularly good support for Nim's
|
||||||
eccentric *style insensitivity*. Apart from that it is a generic text
|
eccentric *style insensitivity*. Apart from that it is a generic text
|
||||||
manipulation tool.
|
manipulation tool.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -34,10 +34,10 @@ Options:
|
||||||
--find, -f find the pattern (default)
|
--find, -f find the pattern (default)
|
||||||
--replace, -r replace the pattern
|
--replace, -r replace the pattern
|
||||||
--peg pattern is a peg
|
--peg pattern is a peg
|
||||||
--re pattern is a regular expression (default); extended
|
--re pattern is a regular expression (default); extended
|
||||||
syntax for the regular expression is always turned on
|
syntax for the regular expression is always turned on
|
||||||
--recursive process directories recursively
|
--recursive process directories recursively
|
||||||
--confirm confirm each occurrence/replacement; there is a chance
|
--confirm confirm each occurrence/replacement; there is a chance
|
||||||
to abort any time without touching the file
|
to abort any time without touching the file
|
||||||
--stdin read pattern from stdin (to avoid the shell's confusing
|
--stdin read pattern from stdin (to avoid the shell's confusing
|
||||||
quoting rules)
|
quoting rules)
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,12 @@ Introduction
|
||||||
============
|
============
|
||||||
|
|
||||||
niminst is a tool to generate an installer for a Nim program. Currently
|
niminst is a tool to generate an installer for a Nim program. Currently
|
||||||
it can create an installer for Windows
|
it can create an installer for Windows
|
||||||
via `Inno Setup <http://www.jrsoftware.org/isinfo.php>`_ as well as
|
via `Inno Setup <http://www.jrsoftware.org/isinfo.php>`_ as well as
|
||||||
installation/deinstallation scripts for UNIX. Later versions will support
|
installation/deinstallation scripts for UNIX. Later versions will support
|
||||||
Linux' package management systems.
|
Linux' package management systems.
|
||||||
|
|
||||||
niminst works by reading a configuration file that contains all the
|
niminst works by reading a configuration file that contains all the
|
||||||
information that it needs to generate an installer for the different operating
|
information that it needs to generate an installer for the different operating
|
||||||
systems.
|
systems.
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@ systems.
|
||||||
Configuration file
|
Configuration file
|
||||||
==================
|
==================
|
||||||
|
|
||||||
niminst uses the Nim `parsecfg <parsecfg.html>`_ module to parse the
|
niminst uses the Nim `parsecfg <parsecfg.html>`_ module to parse the
|
||||||
configuration file. Here's an example of how the syntax looks like:
|
configuration file. Here's an example of how the syntax looks like:
|
||||||
|
|
||||||
.. include:: doc/mytest.cfg
|
.. include:: doc/mytest.cfg
|
||||||
|
|
@ -54,10 +54,10 @@ Key description
|
||||||
``OS`` the OSes to generate C code for; for example:
|
``OS`` the OSes to generate C code for; for example:
|
||||||
``"windows;linux;macosx"``
|
``"windows;linux;macosx"``
|
||||||
``CPU`` the CPUs to generate C code for; for example:
|
``CPU`` the CPUs to generate C code for; for example:
|
||||||
``"i386;amd64;powerpc"``
|
``"i386;amd64;powerpc"``
|
||||||
``Authors`` the project's authors
|
``Authors`` the project's authors
|
||||||
``Description`` the project's description
|
``Description`` the project's description
|
||||||
``App`` the application's type: "Console" or "GUI". If
|
``App`` the application's type: "Console" or "GUI". If
|
||||||
"Console", niminst generates a special batch file
|
"Console", niminst generates a special batch file
|
||||||
for Windows to open up the command line shell.
|
for Windows to open up the command line shell.
|
||||||
``License`` the filename of the application's license
|
``License`` the filename of the application's license
|
||||||
|
|
@ -69,7 +69,7 @@ Key description
|
||||||
|
|
||||||
Many sections support the ``files`` key. Listed filenames
|
Many sections support the ``files`` key. Listed filenames
|
||||||
can be separated by semicolon or the ``files`` key can be repeated. Wildcards
|
can be separated by semicolon or the ``files`` key can be repeated. Wildcards
|
||||||
in filenames are supported. If it is a directory name, all files in the
|
in filenames are supported. If it is a directory name, all files in the
|
||||||
directory are used::
|
directory are used::
|
||||||
|
|
||||||
[Config]
|
[Config]
|
||||||
|
|
@ -87,35 +87,35 @@ will be installed into the OS's configuration directory.
|
||||||
Documentation section
|
Documentation section
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
The ``documentation`` section supports the ``files`` key.
|
The ``documentation`` section supports the ``files`` key.
|
||||||
Listed files will be installed into the OS's native documentation directory
|
Listed files will be installed into the OS's native documentation directory
|
||||||
(which might be ``$appdir/doc``).
|
(which might be ``$appdir/doc``).
|
||||||
|
|
||||||
There is a ``start`` key which determines whether the Windows installer
|
There is a ``start`` key which determines whether the Windows installer
|
||||||
generates a link to e.g. the ``index.html`` of your documentation.
|
generates a link to e.g. the ``index.html`` of your documentation.
|
||||||
|
|
||||||
|
|
||||||
Other section
|
Other section
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
The ``other`` section currently only supports the ``files`` key.
|
The ``other`` section currently only supports the ``files`` key.
|
||||||
Listed files will be installed into the application installation directory
|
Listed files will be installed into the application installation directory
|
||||||
(``$appdir``).
|
(``$appdir``).
|
||||||
|
|
||||||
|
|
||||||
Lib section
|
Lib section
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
The ``lib`` section currently only supports the ``files`` key.
|
The ``lib`` section currently only supports the ``files`` key.
|
||||||
Listed files will be installed into the OS's native library directory
|
Listed files will be installed into the OS's native library directory
|
||||||
(which might be ``$appdir/lib``).
|
(which might be ``$appdir/lib``).
|
||||||
|
|
||||||
|
|
||||||
Windows section
|
Windows section
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
The ``windows`` section supports the ``files`` key for Windows specific files.
|
The ``windows`` section supports the ``files`` key for Windows specific files.
|
||||||
Listed files will be installed into the application installation directory
|
Listed files will be installed into the application installation directory
|
||||||
(``$appdir``).
|
(``$appdir``).
|
||||||
|
|
||||||
Other possible options are:
|
Other possible options are:
|
||||||
|
|
@ -133,8 +133,8 @@ Key description
|
||||||
UnixBin section
|
UnixBin section
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
The ``UnixBin`` section currently only supports the ``files`` key.
|
The ``UnixBin`` section currently only supports the ``files`` key.
|
||||||
Listed files will be installed into the OS's native bin directory
|
Listed files will be installed into the OS's native bin directory
|
||||||
(e.g. ``/usr/local/bin``). The exact location depends on the
|
(e.g. ``/usr/local/bin``). The exact location depends on the
|
||||||
installation path the user specifies when running the ``install.sh`` script.
|
installation path the user specifies when running the ``install.sh`` script.
|
||||||
|
|
||||||
|
|
@ -150,7 +150,7 @@ Key description
|
||||||
``InstallScript`` boolean flag whether an installation shell script
|
``InstallScript`` boolean flag whether an installation shell script
|
||||||
should be generated. Example: ``InstallScript: "Yes"``
|
should be generated. Example: ``InstallScript: "Yes"``
|
||||||
``UninstallScript`` boolean flag whether a deinstallation shell script
|
``UninstallScript`` boolean flag whether a deinstallation shell script
|
||||||
should be generated.
|
should be generated.
|
||||||
Example: ``UninstallScript: "Yes"``
|
Example: ``UninstallScript: "Yes"``
|
||||||
==================== =======================================================
|
==================== =======================================================
|
||||||
|
|
||||||
|
|
@ -163,7 +163,7 @@ Possible options are:
|
||||||
==================== =======================================================
|
==================== =======================================================
|
||||||
Key description
|
Key description
|
||||||
==================== =======================================================
|
==================== =======================================================
|
||||||
``path`` Path to Inno Setup.
|
``path`` Path to Inno Setup.
|
||||||
Example: ``path = r"c:\inno setup 5\iscc.exe"``
|
Example: ``path = r"c:\inno setup 5\iscc.exe"``
|
||||||
``flags`` Flags to pass to Inno Setup.
|
``flags`` Flags to pass to Inno Setup.
|
||||||
Example: ``flags = "/Q"``
|
Example: ``flags = "/Q"``
|
||||||
|
|
@ -178,7 +178,7 @@ Possible options are:
|
||||||
==================== =======================================================
|
==================== =======================================================
|
||||||
Key description
|
Key description
|
||||||
==================== =======================================================
|
==================== =======================================================
|
||||||
``path`` Path to the C compiler.
|
``path`` Path to the C compiler.
|
||||||
``flags`` Flags to pass to the C Compiler.
|
``flags`` Flags to pass to the C Compiler.
|
||||||
Example: ``flags = "-w"``
|
Example: ``flags = "-w"``
|
||||||
==================== =======================================================
|
==================== =======================================================
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ notation meaning
|
||||||
order, to the text ahead, until one of them succeeds and
|
order, to the text ahead, until one of them succeeds and
|
||||||
possibly consumes some text. Indicate success if one of
|
possibly consumes some text. Indicate success if one of
|
||||||
expressions succeeded. Otherwise do not consume any text
|
expressions succeeded. Otherwise do not consume any text
|
||||||
and indicate failure.
|
and indicate failure.
|
||||||
``A ... Z`` Sequence: Apply expressions `A`, ..., `Z`, in this order,
|
``A ... Z`` Sequence: Apply expressions `A`, ..., `Z`, in this order,
|
||||||
to consume consecutive portions of the text ahead, as long
|
to consume consecutive portions of the text ahead, as long
|
||||||
as they succeed. Indicate success if all succeeded.
|
as they succeed. Indicate success if all succeeded.
|
||||||
|
|
@ -27,11 +27,11 @@ notation meaning
|
||||||
``{E}`` Capture: Apply expression `E` and store the substring
|
``{E}`` Capture: Apply expression `E` and store the substring
|
||||||
that matched `E` into a *capture* that can be accessed
|
that matched `E` into a *capture* that can be accessed
|
||||||
after the matching process.
|
after the matching process.
|
||||||
``$i`` Back reference to the ``i``th capture. ``i`` counts from 1.
|
``$i`` Back reference to the ``i``th capture. ``i`` counts from 1.
|
||||||
``$`` Anchor: Matches at the end of the input. No character
|
``$`` Anchor: Matches at the end of the input. No character
|
||||||
is consumed. Same as ``!.``.
|
is consumed. Same as ``!.``.
|
||||||
``^`` Anchor: Matches at the start of the input. No character
|
``^`` Anchor: Matches at the start of the input. No character
|
||||||
is consumed.
|
is consumed.
|
||||||
``&E`` And predicate: Indicate success if expression `E` matches
|
``&E`` And predicate: Indicate success if expression `E` matches
|
||||||
the text ahead; otherwise indicate failure. Do not consume
|
the text ahead; otherwise indicate failure. Do not consume
|
||||||
any text.
|
any text.
|
||||||
|
|
@ -41,15 +41,15 @@ notation meaning
|
||||||
``E+`` One or more: Apply expression `E` repeatedly to match
|
``E+`` One or more: Apply expression `E` repeatedly to match
|
||||||
the text ahead, as long as it succeeds. Consume the matched
|
the text ahead, as long as it succeeds. Consume the matched
|
||||||
text (if any) and indicate success if there was at least
|
text (if any) and indicate success if there was at least
|
||||||
one match. Otherwise indicate failure.
|
one match. Otherwise indicate failure.
|
||||||
``E*`` Zero or more: Apply expression `E` repeatedly to match
|
``E*`` Zero or more: Apply expression `E` repeatedly to match
|
||||||
the text ahead, as long as it succeeds. Consume the matched
|
the text ahead, as long as it succeeds. Consume the matched
|
||||||
text (if any). Always indicate success.
|
text (if any). Always indicate success.
|
||||||
``E?`` Zero or one: If expression `E` matches the text ahead,
|
``E?`` Zero or one: If expression `E` matches the text ahead,
|
||||||
consume it. Always indicate success.
|
consume it. Always indicate success.
|
||||||
``[s]`` Character class: If the character ahead appears in the
|
``[s]`` Character class: If the character ahead appears in the
|
||||||
string `s`, consume it and indicate success. Otherwise
|
string `s`, consume it and indicate success. Otherwise
|
||||||
indicate failure.
|
indicate failure.
|
||||||
``[a-b]`` Character range: If the character ahead is one from the
|
``[a-b]`` Character range: If the character ahead is one from the
|
||||||
range `a` through `b`, consume it and indicate success.
|
range `a` through `b`, consume it and indicate success.
|
||||||
Otherwise indicate failure.
|
Otherwise indicate failure.
|
||||||
|
|
@ -70,7 +70,7 @@ notation meaning
|
||||||
failure.
|
failure.
|
||||||
``@E`` Search: Shorthand for ``(!E .)* E``. (Search loop for the
|
``@E`` Search: Shorthand for ``(!E .)* E``. (Search loop for the
|
||||||
pattern `E`.)
|
pattern `E`.)
|
||||||
``{@} E`` Captured Search: Shorthand for ``{(!E .)*} E``. (Search
|
``{@} E`` Captured Search: Shorthand for ``{(!E .)*} E``. (Search
|
||||||
loop for the pattern `E`.) Everything until and exluding
|
loop for the pattern `E`.) Everything until and exluding
|
||||||
`E` is captured.
|
`E` is captured.
|
||||||
``@@ E`` Same as ``{@} E``.
|
``@@ E`` Same as ``{@} E``.
|
||||||
|
|
@ -79,7 +79,7 @@ notation meaning
|
||||||
matching engine.**
|
matching engine.**
|
||||||
``\identifier`` Built-in macro for a longer expression.
|
``\identifier`` Built-in macro for a longer expression.
|
||||||
``\ddd`` Character with decimal code *ddd*.
|
``\ddd`` Character with decimal code *ddd*.
|
||||||
``\"``, etc Literal ``"``, etc.
|
``\"``, etc Literal ``"``, etc.
|
||||||
=============== ============================================================
|
=============== ============================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -101,9 +101,9 @@ macro meaning
|
||||||
``\n`` any newline combination: ``\10 / \13\10 / \13``
|
``\n`` any newline combination: ``\10 / \13\10 / \13``
|
||||||
``\i`` ignore case for matching; use this at the start of the PEG
|
``\i`` ignore case for matching; use this at the start of the PEG
|
||||||
``\y`` ignore style for matching; use this at the start of the PEG
|
``\y`` ignore style for matching; use this at the start of the PEG
|
||||||
``\skip`` pat skip pattern *pat* before trying to match other tokens;
|
``\skip`` pat skip pattern *pat* before trying to match other tokens;
|
||||||
this is useful for whitespace skipping, for example:
|
this is useful for whitespace skipping, for example:
|
||||||
``\skip(\s*) {\ident} ':' {\ident}`` matches key value
|
``\skip(\s*) {\ident} ':' {\ident}`` matches key value
|
||||||
pairs ignoring whitespace around the ``':'``.
|
pairs ignoring whitespace around the ``':'``.
|
||||||
``\ident`` a standard ASCII identifier: ``[a-zA-Z_][a-zA-Z_0-9]*``
|
``\ident`` a standard ASCII identifier: ``[a-zA-Z_][a-zA-Z_0-9]*``
|
||||||
``\letter`` any Unicode letter
|
``\letter`` any Unicode letter
|
||||||
|
|
@ -133,42 +133,42 @@ The PEG parser implements this grammar (written in PEG syntax)::
|
||||||
# Example grammar of PEG in PEG syntax.
|
# Example grammar of PEG in PEG syntax.
|
||||||
# Comments start with '#'.
|
# Comments start with '#'.
|
||||||
# First symbol is the start symbol.
|
# First symbol is the start symbol.
|
||||||
|
|
||||||
grammar <- rule* / expr
|
grammar <- rule* / expr
|
||||||
|
|
||||||
identifier <- [A-Za-z][A-Za-z0-9_]*
|
identifier <- [A-Za-z][A-Za-z0-9_]*
|
||||||
charsetchar <- "\\" . / [^\]]
|
charsetchar <- "\\" . / [^\]]
|
||||||
charset <- "[" "^"? (charsetchar ("-" charsetchar)?)+ "]"
|
charset <- "[" "^"? (charsetchar ("-" charsetchar)?)+ "]"
|
||||||
stringlit <- identifier? ("\"" ("\\" . / [^"])* "\"" /
|
stringlit <- identifier? ("\"" ("\\" . / [^"])* "\"" /
|
||||||
"'" ("\\" . / [^'])* "'")
|
"'" ("\\" . / [^'])* "'")
|
||||||
builtin <- "\\" identifier / [^\13\10]
|
builtin <- "\\" identifier / [^\13\10]
|
||||||
|
|
||||||
comment <- '#' @ \n
|
comment <- '#' @ \n
|
||||||
ig <- (\s / comment)* # things to ignore
|
ig <- (\s / comment)* # things to ignore
|
||||||
|
|
||||||
rule <- identifier \s* "<-" expr ig
|
rule <- identifier \s* "<-" expr ig
|
||||||
identNoArrow <- identifier !(\s* "<-")
|
identNoArrow <- identifier !(\s* "<-")
|
||||||
prefixOpr <- ig '&' / ig '!' / ig '@' / ig '{@}' / ig '@@'
|
prefixOpr <- ig '&' / ig '!' / ig '@' / ig '{@}' / ig '@@'
|
||||||
literal <- ig identifier? '$' [0-9]+ / '$' / '^' /
|
literal <- ig identifier? '$' [0-9]+ / '$' / '^' /
|
||||||
ig identNoArrow /
|
ig identNoArrow /
|
||||||
ig charset /
|
ig charset /
|
||||||
ig stringlit /
|
ig stringlit /
|
||||||
ig builtin /
|
ig builtin /
|
||||||
ig '.' /
|
ig '.' /
|
||||||
ig '_' /
|
ig '_' /
|
||||||
(ig "(" expr ig ")")
|
(ig "(" expr ig ")")
|
||||||
postfixOpr <- ig '?' / ig '*' / ig '+'
|
postfixOpr <- ig '?' / ig '*' / ig '+'
|
||||||
primary <- prefixOpr* (literal postfixOpr*)
|
primary <- prefixOpr* (literal postfixOpr*)
|
||||||
|
|
||||||
# Concatenation has higher priority than choice:
|
# Concatenation has higher priority than choice:
|
||||||
# ``a b / c`` means ``(a b) / c``
|
# ``a b / c`` means ``(a b) / c``
|
||||||
|
|
||||||
seqExpr <- primary+
|
seqExpr <- primary+
|
||||||
expr <- seqExpr (ig "/" expr)*
|
expr <- seqExpr (ig "/" expr)*
|
||||||
|
|
||||||
|
|
||||||
**Note**: As a special syntactic extension if the whole PEG is only a single
|
**Note**: As a special syntactic extension if the whole PEG is only a single
|
||||||
expression, identifiers are not interpreted as non-terminals, but are
|
expression, identifiers are not interpreted as non-terminals, but are
|
||||||
interpreted as verbatim string:
|
interpreted as verbatim string:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -185,7 +185,7 @@ Check if `s` matches Nim's "while" keyword:
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
s =~ peg" y'while'"
|
s =~ peg" y'while'"
|
||||||
|
|
||||||
Exchange (key, val)-pairs:
|
Exchange (key, val)-pairs:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
"key: val; key2: val2".replacef(peg"{\ident} \s* ':' \s* {\ident}", "$2: $1")
|
"key: val; key2: val2".replacef(peg"{\ident} \s* ':' \s* {\ident}", "$2: $1")
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
============================
|
============================
|
||||||
Nim's documenation system
|
Nim's documenation system
|
||||||
============================
|
============================
|
||||||
|
|
||||||
This folder contains Nim's documentation. The documentation
|
This folder contains Nim's documentation. The documentation
|
||||||
is written in a format called *reStructuredText*, a markup language that reads
|
is written in a format called *reStructuredText*, a markup language that reads
|
||||||
like ASCII and can be converted to HTML automatically!
|
like ASCII and can be converted to HTML automatically!
|
||||||
|
|
|
||||||
|
|
@ -175,17 +175,17 @@ for themselves. For example:
|
||||||
example meaning
|
example meaning
|
||||||
============== ============================================================
|
============== ============================================================
|
||||||
``\040`` is another way of writing a space
|
``\040`` is another way of writing a space
|
||||||
``\40`` is the same, provided there are fewer than 40 previous
|
``\40`` is the same, provided there are fewer than 40 previous
|
||||||
capturing subpatterns
|
capturing subpatterns
|
||||||
``\7`` is always a back reference
|
``\7`` is always a back reference
|
||||||
``\11`` might be a back reference, or another way of writing a tab
|
``\11`` might be a back reference, or another way of writing a tab
|
||||||
``\011`` is always a tab
|
``\011`` is always a tab
|
||||||
``\0113`` is a tab followed by the character "3"
|
``\0113`` is a tab followed by the character "3"
|
||||||
``\113`` might be a back reference, otherwise the character with
|
``\113`` might be a back reference, otherwise the character with
|
||||||
octal code 113
|
octal code 113
|
||||||
``\377`` might be a back reference, otherwise the byte consisting
|
``\377`` might be a back reference, otherwise the byte consisting
|
||||||
entirely of 1 bits
|
entirely of 1 bits
|
||||||
``\81`` is either a back reference, or a binary zero followed by
|
``\81`` is either a back reference, or a binary zero followed by
|
||||||
the two characters "8" and "1"
|
the two characters "8" and "1"
|
||||||
============== ============================================================
|
============== ============================================================
|
||||||
|
|
||||||
|
|
@ -240,7 +240,7 @@ even when Unicode character property support is available.
|
||||||
|
|
||||||
Simple assertions
|
Simple assertions
|
||||||
-----------------
|
-----------------
|
||||||
The fourth use of backslash is for certain `simple assertions`:idx:. An
|
The fourth use of backslash is for certain `simple assertions`:idx:. An
|
||||||
assertion specifies a condition that has to be met at a particular point in
|
assertion specifies a condition that has to be met at a particular point in
|
||||||
a match, without consuming any characters from the subject string. The use of
|
a match, without consuming any characters from the subject string. The use of
|
||||||
subpatterns for more complicated assertions is described below. The
|
subpatterns for more complicated assertions is described below. The
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ basetype can only be an ordinal type of a certain size, namely:
|
||||||
* ``uint8``/``byte``-``uint16``
|
* ``uint8``/``byte``-``uint16``
|
||||||
* ``char``
|
* ``char``
|
||||||
* ``enum``
|
* ``enum``
|
||||||
or equivalent. The reason is that sets are implemented as high
|
or equivalent. The reason is that sets are implemented as high
|
||||||
performance bit vectors. Attempting to declare a set with a larger type will
|
performance bit vectors. Attempting to declare a set with a larger type will
|
||||||
result in an error:
|
result in an error:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
Parallel & Spawn
|
Parallel & Spawn
|
||||||
==========================================================
|
==========================================================
|
||||||
|
|
||||||
Nim has two flavors of parallelism:
|
Nim has two flavors of parallelism:
|
||||||
1) `Structured`:idx parallelism via the ``parallel`` statement.
|
1) `Structured`:idx parallelism via the ``parallel`` statement.
|
||||||
2) `Unstructured`:idx: parallelism via the standalone ``spawn`` statement.
|
2) `Unstructured`:idx: parallelism via the standalone ``spawn`` statement.
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ variables at the same time:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
import threadpool, ...
|
import threadpool, ...
|
||||||
|
|
||||||
# wait until 2 out of 3 servers received the update:
|
# wait until 2 out of 3 servers received the update:
|
||||||
proc main =
|
proc main =
|
||||||
var responses = newSeq[FlowVarBase](3)
|
var responses = newSeq[FlowVarBase](3)
|
||||||
|
|
@ -89,7 +89,7 @@ restrictions / changes:
|
||||||
the ``parallel`` section. This is called the *immutability check*. Currently
|
the ``parallel`` section. This is called the *immutability check*. Currently
|
||||||
it is not specified what exactly "complex location" means. We need to make
|
it is not specified what exactly "complex location" means. We need to make
|
||||||
this an optimization!
|
this an optimization!
|
||||||
* Every array access has to be provably within bounds. This is called
|
* Every array access has to be provably within bounds. This is called
|
||||||
the *bounds check*.
|
the *bounds check*.
|
||||||
* Slices are optimized so that no copy is performed. This optimization is not
|
* Slices are optimized so that no copy is performed. This optimization is not
|
||||||
yet performed for ordinary slices outside of a ``parallel`` section. Slices
|
yet performed for ordinary slices outside of a ``parallel`` section. Slices
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
Substitution Expressions (subex)
|
Substitution Expressions (subex)
|
||||||
================================
|
================================
|
||||||
|
|
||||||
A *subex* (*Substitution Expression*) represents an advanted string
|
A *subex* (*Substitution Expression*) represents an advanted string
|
||||||
substitution. In contrast to a `regex`:idx: which deals with string analysis, a
|
substitution. In contrast to a `regex`:idx: which deals with string analysis, a
|
||||||
*subex* deals with string synthesis.
|
*subex* deals with string synthesis.
|
||||||
|
|
||||||
Thanks to its conditional construct ``$[0|1|2|else]`` it supports
|
Thanks to its conditional construct ``$[0|1|2|else]`` it supports
|
||||||
`internationalization`:idx: of format string literals quite well.
|
`internationalization`:idx: of format string literals quite well.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -37,7 +37,7 @@ Notation meaning
|
||||||
``$[zero|one|def]1`` use ``X = parseInt(arg[1])`` to determine which
|
``$[zero|one|def]1`` use ``X = parseInt(arg[1])`` to determine which
|
||||||
branch to use. If ``X == 0`` the 'zero' branch is
|
branch to use. If ``X == 0`` the 'zero' branch is
|
||||||
selected, if ``X == 1`` the 'one' branch is
|
selected, if ``X == 1`` the 'one' branch is
|
||||||
selected, etc. Otherwise the 'def' branch is
|
selected, etc. Otherwise the 'def' branch is
|
||||||
selected. ``$x`` is interpreted in branches too.
|
selected. ``$x`` is interpreted in branches too.
|
||||||
If a branch needs to contain ``|``, ``]`` put
|
If a branch needs to contain ``|``, ``]`` put
|
||||||
them in single quotes. To produce a verbatim single
|
them in single quotes. To produce a verbatim single
|
||||||
|
|
@ -50,12 +50,12 @@ Examples
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
subex"$1($', '{2..})" % ["f", "a", "b", "c"] == "f(a, b, c)"
|
subex"$1($', '{2..})" % ["f", "a", "b", "c"] == "f(a, b, c)"
|
||||||
|
|
||||||
subex"$1 $[files|file|files]{1} copied" % ["1"] == "1 file copied"
|
subex"$1 $[files|file|files]{1} copied" % ["1"] == "1 file copied"
|
||||||
|
|
||||||
subex"$['''|'|''''|']']#" % "0" == "'|"
|
subex"$['''|'|''''|']']#" % "0" == "'|"
|
||||||
|
|
||||||
subex("type\n TEnum = enum\n $', '40c'\n '{..}") % [
|
subex("type\n TEnum = enum\n $', '40c'\n '{..}") % [
|
||||||
"fieldNameA", "fieldNameB", "fieldNameC", "fieldNameD"]
|
"fieldNameA", "fieldNameB", "fieldNameC", "fieldNameD"]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
10
doc/tut1.txt
10
doc/tut1.txt
|
|
@ -1280,19 +1280,19 @@ with a compatible base type can be passed to an openarray parameter, the index
|
||||||
type does not matter.
|
type does not matter.
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
var
|
var
|
||||||
fruits: seq[string] # reference to a sequence of strings that is initialized with 'nil'
|
fruits: seq[string] # reference to a sequence of strings that is initialized with 'nil'
|
||||||
capitals: array[3, string] # array of strings with a fixed size
|
capitals: array[3, string] # array of strings with a fixed size
|
||||||
|
|
||||||
fruits = @[] # creates an empty sequence on the heap that will be referenced by 'fruits'
|
fruits = @[] # creates an empty sequence on the heap that will be referenced by 'fruits'
|
||||||
|
|
||||||
capitals = ["New York", "London", "Berlin"] # array 'capitals' allows only assignment of three elements
|
capitals = ["New York", "London", "Berlin"] # array 'capitals' allows only assignment of three elements
|
||||||
fruits.add("Banana") # sequence 'fruits' is dynamically expandable during runtime
|
fruits.add("Banana") # sequence 'fruits' is dynamically expandable during runtime
|
||||||
fruits.add("Mango")
|
fruits.add("Mango")
|
||||||
|
|
||||||
proc openArraySize(oa: openArray[string]): int =
|
proc openArraySize(oa: openArray[string]): int =
|
||||||
oa.len
|
oa.len
|
||||||
|
|
||||||
assert openArraySize(fruits) == 2 # procedure accepts a sequence as parameter
|
assert openArraySize(fruits) == 2 # procedure accepts a sequence as parameter
|
||||||
assert openArraySize(capitals) == 3 # but also an array type
|
assert openArraySize(capitals) == 3 # but also an array type
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue