bind table

This commit is contained in:
Andreas Rumpf 2009-11-12 19:34:21 +01:00
commit ac421c37ba
18 changed files with 957 additions and 384 deletions

View file

@ -20,7 +20,7 @@ contains:
PNimrodNode = ref TNimrodNode PNimrodNode = ref TNimrodNode
TNimrodNode {.final.} = object TNimrodNode {.final.} = object
case kind ## the node's kind case kind: TNimrodNodeKind ## the node's kind
of nnkNone, nnkEmpty, nnkNilLit: of nnkNone, nnkEmpty, nnkNilLit:
nil ## node contains no additional fields nil ## node contains no additional fields
of nnkCharLit..nnkInt64Lit: of nnkCharLit..nnkInt64Lit:
@ -43,6 +43,11 @@ To specify the AST for the different Nimrod constructs, the notation
``nodekind(son1, son2, ...)`` or ``nodekind(value)`` or ``nodekind(son1, son2, ...)`` or ``nodekind(value)`` or
``nodekind(field=value)`` is used. ``nodekind(field=value)`` is used.
Some child may be missing. Then it is ``nil``. A nil child is equivalent to
a node of kind ``nnkEmpty``. This is more or less a (useful) artifact from
the implementation. (In the compiler's implementation ``nil`` is of course
not the same as ``nnkEmpty``!)
Leaf nodes/Atoms Leaf nodes/Atoms
================ ================
@ -72,8 +77,9 @@ Nimrod expression corresponding AST
Identifiers are ``nnkIdent`` nodes. After the name lookup pass these nodes Identifiers are ``nnkIdent`` nodes. After the name lookup pass these nodes
get transferred into ``nnkSym`` nodes. However, a macro receives an AST that get transferred into ``nnkSym`` nodes. However, a macro receives an AST that
has not been checked for semantics and thus the identifiers have not been has not been checked for semantics and thus the identifiers have not been
looked up. Thus macros deal with ``nnkIdent`` nodes. looked up. Macros should deal with ``nnkIdent`` nodes and do not need to deal
with ``nnkSym`` nodes.
Calls/expressions Calls/expressions
================= =================

View file

@ -4,8 +4,8 @@ Parsers and Filters
.. contents:: .. contents::
The Nimrod compiler contains multiple parsers. (The standard is The Nimrod compiler contains multiple parsers. The standard is
indentation-based.) Two others are available: The `braces`:idx: parser and the indentation-based. Two others are available: The `braces`:idx: parser and the
`endX`:idx: parser. Both parsers use the same lexer as the standard parser. `endX`:idx: parser. Both parsers use the same lexer as the standard parser.
To use a different parser for a source file the *shebang* notation is used: To use a different parser for a source file the *shebang* notation is used:

View file

@ -951,7 +951,7 @@ of the following conditions hold:
3) The procedure has a calling convention that differs from ``nimcall``. 3) The procedure has a calling convention that differs from ``nimcall``.
4) The procedure is anonymous. 4) The procedure is anonymous.
These rules should prevent the case that extending a non-``procvar`` The rules' purpose is to prevent the case that extending a non-``procvar``
procedure with default parameters breaks client code. procedure with default parameters breaks client code.
@ -1800,7 +1800,7 @@ return values. This can be done in a cleaner way by returning a tuple:
assert t.res == 1 assert t.res == 1
assert t.remainder = 3 assert t.remainder = 3
Even more elegant is to use `tuple unpacking`:idx: to access the tuple's fields: One can use `tuple unpacking`:idx: to access the tuple's fields:
.. code-block:: nimrod .. code-block:: nimrod
var (x, y) = divmod(8, 5) # tuple unpacking var (x, y) = divmod(8, 5) # tuple unpacking
@ -1872,7 +1872,7 @@ dispatching:
Invokation of a multi-method cannot be ambiguous: Collide 2 is prefered over Invokation of a multi-method cannot be ambiguous: Collide 2 is prefered over
collide 1 because the resolution works from left to right. collide 1 because the resolution works from left to right.
Thus ``TUnit, TThing`` is prefered over ``TThing, TUnit``. In the example ``TUnit, TThing`` is prefered over ``TThing, TUnit``.
**Perfomance note**: Nimrod does not produce a virtual method table, but **Perfomance note**: Nimrod does not produce a virtual method table, but
generates dispatch trees. This avoids the expensive indirect branch for method generates dispatch trees. This avoids the expensive indirect branch for method
@ -2112,6 +2112,44 @@ special ``:`` syntax:
In the example the two ``writeln`` statements are bound to the ``actions`` In the example the two ``writeln`` statements are bound to the ``actions``
parameter. parameter.
Symbol binding within templates happens after template instantation:
.. code-block:: nimrod
# Module A
var
lastId = 0
template genId*: expr =
inc(lastId)
lastId
.. code-block:: nimrod
# Module B
import A
echo genId() # Error: undeclared identifier: 'lastId'
Exporting a template is a often a leaky abstraction. However, to compensate for
this case, the ``bind`` operator can be used: All identifiers
within a ``bind`` context are bound early (i.e. when the template is parsed).
The affected identifiers are then always bound early even if the other
occurences are in no ``bind`` context:
.. code-block:: nimrod
# Module A
var
lastId = 0
template genId*: expr =
inc(bind lastId)
lastId
.. code-block:: nimrod
# Module B
import A
echo genId() # Works
**Style note**: For code readability, it is the best idea to use the least **Style note**: For code readability, it is the best idea to use the least
powerful programming construct that still suffices. So the "check list" is: powerful programming construct that still suffices. So the "check list" is:
@ -2356,7 +2394,7 @@ verify this.
procvar pragma procvar pragma
-------------- --------------
The `procvar`:idx: pragma is used to mark a proc that it can be passed to a The `procvar`:idx: pragma is used to mark a proc so that it can be passed to a
procedural variable. procedural variable.

View file

@ -109,6 +109,21 @@ In general, importing a dynamic library does not require any special linker
options or linking with import libraries. This also implies that no *devel* options or linking with import libraries. This also implies that no *devel*
packages need to be installed. packages need to be installed.
The ``dynlib`` import mechanism supports a versioning scheme:
.. code-block:: nimrod
proc Tcl_Eval(interp: pTcl_Interp, script: cstring): int {.cdecl,
importc, dynlib: "libtcl(8.5|8.4|8.3).so.(1|0)".}
At runtime the dynamic library is searched for (in this order)::
libtcl8.5.so.1
libtcl8.4.so.1
libtcl8.3.so.1
libtcl8.5.so.0
libtcl8.4.so.0
libtcl8.3.so.0
No_decl Pragma No_decl Pragma
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
@ -231,7 +246,7 @@ compiler to activate (or deactivate) dead code elimination for the module the
pragma appers in. pragma appers in.
The ``--dead_code_elim:on`` command line switch has the same effect as marking The ``--dead_code_elim:on`` command line switch has the same effect as marking
any module with ``{.dead_code_elim:on}``. However, for some modules such as every module with ``{.dead_code_elim:on}``. However, for some modules such as
the GTK wrapper it makes sense to *always* turn on dead code elimination - the GTK wrapper it makes sense to *always* turn on dead code elimination -
no matter if it is globally active or not. no matter if it is globally active or not.
@ -244,7 +259,7 @@ Example:
Disabling certain messages Disabling certain messages
-------------------------- --------------------------
Nimrod generates some warnings and hints ("line too long") that may annoy the Nimrod generates some warnings and hints ("line too long") that may annoy the
user. Thus a mechanism for disabling certain messages is provided: Each hint user. A mechanism for disabling certain messages is provided: Each hint
and warning message contains a symbol in brackets. This is the message's and warning message contains a symbol in brackets. This is the message's
identifier that can be used to enable or disable it: identifier that can be used to enable or disable it:
@ -300,9 +315,10 @@ However it is not efficient to do:
.. code-block:: Nimrod .. code-block:: Nimrod
var s = varA # assignment has to copy the whole string into a new buffer! var s = varA # assignment has to copy the whole string into a new buffer!
String case statements are optimized too. A hashing scheme is used for them ..
if several different string constants are used. This is likely to be more String case statements are optimized too. A hashing scheme is used for them
efficient than any hand-coded scheme. if several different string constants are used. This is likely to be more
efficient than any hand-coded scheme.
.. ..

View file

@ -60,6 +60,8 @@ notation meaning
``_`` Any Unicode character: If there is an UTF-8 character ``_`` Any Unicode character: If there is an UTF-8 character
ahead, consume it and indicate success. Otherwise indicate ahead, consume it and indicate success. Otherwise indicate
failure. failure.
``@E`` Search: Shorthand for ``(!E .)* E``. (Search loop for the
pattern `E`.)
``A <- E`` Rule: Bind the expression `E` to the *nonterminal symbol* ``A <- E`` Rule: Bind the expression `E` to the *nonterminal symbol*
`A`. **Left recursive rules are not possible and crash the `A`. **Left recursive rules are not possible and crash the
matching engine.** matching engine.**
@ -118,14 +120,15 @@ The PEG parser implements this grammar (written in PEG syntax)::
"'" ("\\" . / [^'])* "'") "'" ("\\" . / [^'])* "'")
builtin <- "\\" identifier / [^\13\10] builtin <- "\\" identifier / [^\13\10]
comment <- '#' !\n* \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* "<-")
primary <- (ig '&' / ig '!')* ((ig identNoArrow / ig charset / ig stringlit primary <- (ig '&' / ig '!' / ig '@')*
/ ig builtin / ig '.' / ig '_' ((ig identNoArrow / ig charset / ig stringlit
/ (ig "(" expr ig ")")) / ig builtin / ig '.' / ig '_'
/ (ig "(" expr ig ")"))
(ig '?' / ig '*' / ig '+')*) (ig '?' / ig '*' / ig '+')*)
# Concatenation has higher priority than choice: # Concatenation has higher priority than choice:
@ -153,16 +156,16 @@ Determine the ``#include``'ed files of a C file:
.. code-block:: nimrod .. code-block:: nimrod
for line in lines("myfile.c"): for line in lines("myfile.c"):
if line =~ peg"""s <- ws '#include' ws '"' {[^"]+} '"' ws if line =~ peg"""s <- ws '#include' ws '"' {[^"]+} '"' ws
comment <- '/*' (!'*/' . )* '*/' / '//' .* comment <- '/*' @ '*/' / '//' .*
ws <- (comment / \s+)* """: ws <- (comment / \s+)* """:
echo matches[0] echo matches[0]
PEG vs regular expression PEG vs regular expression
------------------------- -------------------------
As a regular expression ``\[.*\]`` maches longest possible text between ``'['`` As a regular expression ``\[.*\]`` matches the longest possible text between
and ``']'``. As a PEG it never matches anything, because a PEG is ``'['`` and ``']'``. As a PEG it never matches anything, because a PEG is
deterministic: ``.*`` consumes the rest of the input, so ``\]`` never matches. deterministic: ``.*`` consumes the rest of the input, so ``\]`` never matches.
As a PEG this needs to be written as: ``\[ ( !\] . )* \]`` As a PEG this needs to be written as: ``\[ ( !\] . )* \]`` (or ``\[ @ \]``).
Note that the regular expression does not behave as intended either: Note that the regular expression does not behave as intended either:
``*`` should not be greedy, so ``\[.*?\]`` should be used. ``*`` should not be greedy, so ``\[.*?\]`` should be used.

View file

@ -7,7 +7,7 @@ Index
`!`:idx: `!`:idx:
* `pegs.html#114 <pegs.html#114>`_ * `pegs.html#115 <pegs.html#115>`_
* `macros.html#114 <macros.html#114>`_ * `macros.html#114 <macros.html#114>`_
`!=`:idx: `!=`:idx:
@ -24,7 +24,7 @@ Index
* `system.html#426 <system.html#426>`_ * `system.html#426 <system.html#426>`_
* `times.html#109 <times.html#109>`_ * `times.html#109 <times.html#109>`_
* `times.html#110 <times.html#110>`_ * `times.html#110 <times.html#110>`_
* `pegs.html#148 <pegs.html#148>`_ * `pegs.html#133 <pegs.html#133>`_
* `macros.html#115 <macros.html#115>`_ * `macros.html#115 <macros.html#115>`_
`%`:idx: `%`:idx:
@ -47,7 +47,7 @@ Index
* `system.html#462 <system.html#462>`_ * `system.html#462 <system.html#462>`_
* `system.html#463 <system.html#463>`_ * `system.html#463 <system.html#463>`_
* `system.html#464 <system.html#464>`_ * `system.html#464 <system.html#464>`_
* `pegs.html#113 <pegs.html#113>`_ * `pegs.html#114 <pegs.html#114>`_
`*`:idx: `*`:idx:
* `system.html#212 <system.html#212>`_ * `system.html#212 <system.html#212>`_
@ -82,7 +82,7 @@ Index
* `system.html#309 <system.html#309>`_ * `system.html#309 <system.html#309>`_
* `system.html#320 <system.html#320>`_ * `system.html#320 <system.html#320>`_
* `complex.html#103 <complex.html#103>`_ * `complex.html#103 <complex.html#103>`_
* `pegs.html#112 <pegs.html#112>`_ * `pegs.html#113 <pegs.html#113>`_
`+%`:idx: `+%`:idx:
* `system.html#272 <system.html#272>`_ * `system.html#272 <system.html#272>`_
@ -152,9 +152,6 @@ Index
* `system.html#346 <system.html#346>`_ * `system.html#346 <system.html#346>`_
* `times.html#114 <times.html#114>`_ * `times.html#114 <times.html#114>`_
`<%`:idx:
`unicode.html#104 <unicode.html#104>`_
`<%`:idx: `<%`:idx:
* `system.html#302 <system.html#302>`_ * `system.html#302 <system.html#302>`_
* `system.html#303 <system.html#303>`_ * `system.html#303 <system.html#303>`_
@ -162,6 +159,9 @@ Index
* `system.html#305 <system.html#305>`_ * `system.html#305 <system.html#305>`_
* `system.html#306 <system.html#306>`_ * `system.html#306 <system.html#306>`_
`<%`:idx:
`unicode.html#104 <unicode.html#104>`_
`<=`:idx: `<=`:idx:
* `system.html#257 <system.html#257>`_ * `system.html#257 <system.html#257>`_
* `system.html#258 <system.html#258>`_ * `system.html#258 <system.html#258>`_
@ -180,6 +180,9 @@ Index
`<=`:idx: `<=`:idx:
`times.html#115 <times.html#115>`_ `times.html#115 <times.html#115>`_
`<=%`:idx:
`unicode.html#103 <unicode.html#103>`_
`<=%`:idx: `<=%`:idx:
* `system.html#297 <system.html#297>`_ * `system.html#297 <system.html#297>`_
* `system.html#298 <system.html#298>`_ * `system.html#298 <system.html#298>`_
@ -187,9 +190,6 @@ Index
* `system.html#300 <system.html#300>`_ * `system.html#300 <system.html#300>`_
* `system.html#301 <system.html#301>`_ * `system.html#301 <system.html#301>`_
`<=%`:idx:
`unicode.html#103 <unicode.html#103>`_
`==`:idx: `==`:idx:
* `md5.html#107 <md5.html#107>`_ * `md5.html#107 <md5.html#107>`_
* `system.html#252 <system.html#252>`_ * `system.html#252 <system.html#252>`_
@ -211,12 +211,13 @@ Index
* `complex.html#102 <complex.html#102>`_ * `complex.html#102 <complex.html#102>`_
* `unicode.html#105 <unicode.html#105>`_ * `unicode.html#105 <unicode.html#105>`_
* `macros.html#116 <macros.html#116>`_ * `macros.html#116 <macros.html#116>`_
* `macros.html#117 <macros.html#117>`_
`=~`:idx: `=~`:idx:
`pegs.html#138 <pegs.html#138>`_ `regexprs.html#111 <regexprs.html#111>`_
`=~`:idx: `=~`:idx:
`regexprs.html#108 <regexprs.html#108>`_ `pegs.html#140 <pegs.html#140>`_
`>`:idx: `>`:idx:
`system.html#349 <system.html#349>`_ `system.html#349 <system.html#349>`_
@ -234,14 +235,15 @@ Index
`pegs.html#110 <pegs.html#110>`_ `pegs.html#110 <pegs.html#110>`_
`@`:idx: `@`:idx:
`system.html#357 <system.html#357>`_ * `system.html#357 <system.html#357>`_
* `pegs.html#112 <pegs.html#112>`_
`[]`:idx:
`strtabs.html#107 <strtabs.html#107>`_
`[]`:idx: `[]`:idx:
`macros.html#112 <macros.html#112>`_ `macros.html#112 <macros.html#112>`_
`[]`:idx:
`strtabs.html#107 <strtabs.html#107>`_
`[]=`:idx: `[]=`:idx:
`macros.html#113 <macros.html#113>`_ `macros.html#113 <macros.html#113>`_
@ -279,8 +281,8 @@ Index
* `system.html#368 <system.html#368>`_ * `system.html#368 <system.html#368>`_
* `system.html#369 <system.html#369>`_ * `system.html#369 <system.html#369>`_
* `parsesql.html#108 <parsesql.html#108>`_ * `parsesql.html#108 <parsesql.html#108>`_
* `macros.html#118 <macros.html#118>`_
* `macros.html#119 <macros.html#119>`_ * `macros.html#119 <macros.html#119>`_
* `macros.html#120 <macros.html#120>`_
`addf`:idx: `addf`:idx:
`strutils.html#111 <strutils.html#111>`_ `strutils.html#111 <strutils.html#111>`_
@ -332,17 +334,17 @@ Index
* `system.html#241 <system.html#241>`_ * `system.html#241 <system.html#241>`_
`any`:idx: `any`:idx:
`pegs.html#116 <pegs.html#116>`_
`any character`:idx:
`pegs.html#115 <pegs.html#115>`_
`any rune`:idx:
`pegs.html#117 <pegs.html#117>`_ `pegs.html#117 <pegs.html#117>`_
`anyRune`:idx: `any character`:idx:
`pegs.html#116 <pegs.html#116>`_
`any rune`:idx:
`pegs.html#118 <pegs.html#118>`_ `pegs.html#118 <pegs.html#118>`_
`anyRune`:idx:
`pegs.html#119 <pegs.html#119>`_
`apostrophe`:idx: `apostrophe`:idx:
`manual.html#129 <manual.html#129>`_ `manual.html#129 <manual.html#129>`_
@ -403,7 +405,8 @@ Index
`xmlgen.html#111 <xmlgen.html#111>`_ `xmlgen.html#111 <xmlgen.html#111>`_
`backslash`:idx: `backslash`:idx:
`manual.html#127 <manual.html#127>`_ * `manual.html#127 <manual.html#127>`_
* `regexprs.html#101 <regexprs.html#101>`_
`backspace`:idx: `backspace`:idx:
`manual.html#132 <manual.html#132>`_ `manual.html#132 <manual.html#132>`_
@ -476,7 +479,7 @@ Index
`xmlgen.html#118 <xmlgen.html#118>`_ `xmlgen.html#118 <xmlgen.html#118>`_
`capture`:idx: `capture`:idx:
`pegs.html#121 <pegs.html#121>`_ `pegs.html#122 <pegs.html#122>`_
`card`:idx: `card`:idx:
`system.html#175 <system.html#175>`_ `system.html#175 <system.html#175>`_
@ -695,12 +698,12 @@ Index
`CompileDate`:idx: `CompileDate`:idx:
`system.html#390 <system.html#390>`_ `system.html#390 <system.html#390>`_
`CompileTime`:idx:
`system.html#391 <system.html#391>`_
`compileTime`:idx: `compileTime`:idx:
`manual.html#229 <manual.html#229>`_ `manual.html#229 <manual.html#229>`_
`CompileTime`:idx:
`system.html#391 <system.html#391>`_
`complex statements`:idx: `complex statements`:idx:
`manual.html#178 <manual.html#178>`_ `manual.html#178 <manual.html#178>`_
@ -719,8 +722,8 @@ Index
* `strutils.html#137 <strutils.html#137>`_ * `strutils.html#137 <strutils.html#137>`_
* `strutils.html#138 <strutils.html#138>`_ * `strutils.html#138 <strutils.html#138>`_
* `strutils.html#139 <strutils.html#139>`_ * `strutils.html#139 <strutils.html#139>`_
* `pegs.html#139 <pegs.html#139>`_ * `pegs.html#141 <pegs.html#141>`_
* `pegs.html#140 <pegs.html#140>`_ * `pegs.html#142 <pegs.html#142>`_
`continue`:idx: `continue`:idx:
`manual.html#198 <manual.html#198>`_ `manual.html#198 <manual.html#198>`_
@ -736,10 +739,10 @@ Index
`system.html#407 <system.html#407>`_ `system.html#407 <system.html#407>`_
`copyNimNode`:idx: `copyNimNode`:idx:
`macros.html#135 <macros.html#135>`_ `macros.html#136 <macros.html#136>`_
`copyNimTree`:idx: `copyNimTree`:idx:
`macros.html#136 <macros.html#136>`_ `macros.html#137 <macros.html#137>`_
`coreAttr`:idx: `coreAttr`:idx:
`xmlgen.html#103 <xmlgen.html#103>`_ `xmlgen.html#103 <xmlgen.html#103>`_
@ -1185,7 +1188,7 @@ Index
`del`:idx: `del`:idx:
* `xmlgen.html#124 <xmlgen.html#124>`_ * `xmlgen.html#124 <xmlgen.html#124>`_
* `macros.html#120 <macros.html#120>`_ * `macros.html#121 <macros.html#121>`_
`delete`:idx: `delete`:idx:
`strutils.html#156 <strutils.html#156>`_ `strutils.html#156 <strutils.html#156>`_
@ -1198,7 +1201,7 @@ Index
`xmlgen.html#125 <xmlgen.html#125>`_ `xmlgen.html#125 <xmlgen.html#125>`_
`digits`:idx: `digits`:idx:
`pegs.html#125 <pegs.html#125>`_ `pegs.html#126 <pegs.html#126>`_
`Digits`:idx: `Digits`:idx:
`strutils.html#104 <strutils.html#104>`_ `strutils.html#104 <strutils.html#104>`_
@ -1290,10 +1293,10 @@ Index
`system.html#160 <system.html#160>`_ `system.html#160 <system.html#160>`_
`EInvalidPeg`:idx: `EInvalidPeg`:idx:
`pegs.html#149 <pegs.html#149>`_ `pegs.html#150 <pegs.html#150>`_
`EInvalidRegEx`:idx: `EInvalidRegEx`:idx:
`regexprs.html#101 <regexprs.html#101>`_ `regexprs.html#104 <regexprs.html#104>`_
`EInvalidSql`:idx: `EInvalidSql`:idx:
`parsesql.html#103 <parsesql.html#103>`_ `parsesql.html#103 <parsesql.html#103>`_
@ -1322,7 +1325,7 @@ Index
`endsWith`:idx: `endsWith`:idx:
* `strutils.html#148 <strutils.html#148>`_ * `strutils.html#148 <strutils.html#148>`_
* `pegs.html#142 <pegs.html#142>`_ * `pegs.html#144 <pegs.html#144>`_
`ENoExceptionToReraise`:idx: `ENoExceptionToReraise`:idx:
* `manual.html#187 <manual.html#187>`_ * `manual.html#187 <manual.html#187>`_
@ -1334,12 +1337,12 @@ Index
`enum_cursor_type`:idx: `enum_cursor_type`:idx:
`mysql.html#237 <mysql.html#237>`_ `mysql.html#237 <mysql.html#237>`_
`Enumeration`:idx:
`manual.html#149 <manual.html#149>`_
`enumeration`:idx: `enumeration`:idx:
`tut1.html#113 <tut1.html#113>`_ `tut1.html#113 <tut1.html#113>`_
`Enumeration`:idx:
`manual.html#149 <manual.html#149>`_
`enum_field_types`:idx: `enum_field_types`:idx:
`mysql.html#202 <mysql.html#202>`_ `mysql.html#202 <mysql.html#202>`_
@ -1390,7 +1393,7 @@ Index
`error`:idx: `error`:idx:
* `manual.html#226 <manual.html#226>`_ * `manual.html#226 <manual.html#226>`_
* `manual.html#230 <manual.html#230>`_ * `manual.html#230 <manual.html#230>`_
* `macros.html#137 <macros.html#137>`_ * `macros.html#138 <macros.html#138>`_
`errorMsg`:idx: `errorMsg`:idx:
`parsexml.html#120 <parsexml.html#120>`_ `parsexml.html#120 <parsexml.html#120>`_
@ -1478,13 +1481,13 @@ Index
`os.html#132 <os.html#132>`_ `os.html#132 <os.html#132>`_
`expectKind`:idx: `expectKind`:idx:
`macros.html#146 <macros.html#146>`_ `macros.html#147 <macros.html#147>`_
`expectLen`:idx: `expectLen`:idx:
`macros.html#148 <macros.html#148>`_ `macros.html#149 <macros.html#149>`_
`expectMinLen`:idx: `expectMinLen`:idx:
`macros.html#147 <macros.html#147>`_ `macros.html#148 <macros.html#148>`_
`exportc`:idx: `exportc`:idx:
`nimrodc.html#102 <nimrodc.html#102>`_ `nimrodc.html#102 <nimrodc.html#102>`_
@ -1632,10 +1635,10 @@ Index
* `strutils.html#119 <strutils.html#119>`_ * `strutils.html#119 <strutils.html#119>`_
* `strutils.html#120 <strutils.html#120>`_ * `strutils.html#120 <strutils.html#120>`_
* `strutils.html#121 <strutils.html#121>`_ * `strutils.html#121 <strutils.html#121>`_
* `regexprs.html#106 <regexprs.html#106>`_ * `regexprs.html#109 <regexprs.html#109>`_
* `regexprs.html#107 <regexprs.html#107>`_ * `regexprs.html#110 <regexprs.html#110>`_
* `pegs.html#136 <pegs.html#136>`_ * `pegs.html#138 <pegs.html#138>`_
* `pegs.html#137 <pegs.html#137>`_ * `pegs.html#139 <pegs.html#139>`_
`float`:idx: `float`:idx:
`system.html#106 <system.html#106>`_ `system.html#106 <system.html#106>`_
@ -1647,10 +1650,10 @@ Index
`system.html#108 <system.html#108>`_ `system.html#108 <system.html#108>`_
`floatVal`:idx: `floatVal`:idx:
`macros.html#123 <macros.html#123>`_ `macros.html#124 <macros.html#124>`_
`floatVal=`:idx: `floatVal=`:idx:
`macros.html#129 <macros.html#129>`_ `macros.html#130 <macros.html#130>`_
`FlushFile`:idx: `FlushFile`:idx:
`system.html#503 <system.html#503>`_ `system.html#503 <system.html#503>`_
@ -1715,6 +1718,9 @@ Index
`generalized raw string literal`:idx: `generalized raw string literal`:idx:
`manual.html#136 <manual.html#136>`_ `manual.html#136 <manual.html#136>`_
`generic character types`:idx:
`regexprs.html#102 <regexprs.html#102>`_
`Generics`:idx: `Generics`:idx:
* `manual.html#212 <manual.html#212>`_ * `manual.html#212 <manual.html#212>`_
* `tut2.html#109 <tut2.html#109>`_ * `tut2.html#109 <tut2.html#109>`_
@ -1987,7 +1993,7 @@ Index
`hint`:idx: `hint`:idx:
* `manual.html#224 <manual.html#224>`_ * `manual.html#224 <manual.html#224>`_
* `manual.html#233 <manual.html#233>`_ * `manual.html#233 <manual.html#233>`_
* `macros.html#139 <macros.html#139>`_ * `macros.html#140 <macros.html#140>`_
`hostCPU`:idx: `hostCPU`:idx:
`system.html#398 <system.html#398>`_ `system.html#398 <system.html#398>`_
@ -2001,13 +2007,13 @@ Index
`hr`:idx: `hr`:idx:
`xmlgen.html#140 <xmlgen.html#140>`_ `xmlgen.html#140 <xmlgen.html#140>`_
`html`:idx:
`xmlgen.html#139 <xmlgen.html#139>`_
`HTML`:idx: `HTML`:idx:
* `parsexml.html#102 <parsexml.html#102>`_ * `parsexml.html#102 <parsexml.html#102>`_
* `xmlgen.html#102 <xmlgen.html#102>`_ * `xmlgen.html#102 <xmlgen.html#102>`_
`html`:idx:
`xmlgen.html#139 <xmlgen.html#139>`_
`HTTPPOST_BUFFER`:idx: `HTTPPOST_BUFFER`:idx:
`libcurl.html#266 <libcurl.html#266>`_ `libcurl.html#266 <libcurl.html#266>`_
@ -2033,14 +2039,14 @@ Index
`xmlgen.html#141 <xmlgen.html#141>`_ `xmlgen.html#141 <xmlgen.html#141>`_
`ident`:idx: `ident`:idx:
* `pegs.html#129 <pegs.html#129>`_ * `pegs.html#130 <pegs.html#130>`_
* `macros.html#125 <macros.html#125>`_ * `macros.html#126 <macros.html#126>`_
`ident=`:idx: `ident=`:idx:
`macros.html#131 <macros.html#131>`_ `macros.html#132 <macros.html#132>`_
`identChars`:idx: `identChars`:idx:
`pegs.html#127 <pegs.html#127>`_ `pegs.html#128 <pegs.html#128>`_
`IdentChars`:idx: `IdentChars`:idx:
`strutils.html#105 <strutils.html#105>`_ `strutils.html#105 <strutils.html#105>`_
@ -2052,7 +2058,7 @@ Index
`manual.html#116 <manual.html#116>`_ `manual.html#116 <manual.html#116>`_
`identStartChars`:idx: `identStartChars`:idx:
`pegs.html#128 <pegs.html#128>`_ `pegs.html#129 <pegs.html#129>`_
`IdentStartChars`:idx: `IdentStartChars`:idx:
`strutils.html#106 <strutils.html#106>`_ `strutils.html#106 <strutils.html#106>`_
@ -2138,10 +2144,10 @@ Index
`strutils.html#141 <strutils.html#141>`_ `strutils.html#141 <strutils.html#141>`_
`intVal`:idx: `intVal`:idx:
`macros.html#122 <macros.html#122>`_ `macros.html#123 <macros.html#123>`_
`intVal=`:idx: `intVal=`:idx:
`macros.html#128 <macros.html#128>`_ `macros.html#129 <macros.html#129>`_
`is`:idx: `is`:idx:
`system.html#353 <system.html#353>`_ `system.html#353 <system.html#353>`_
@ -2226,7 +2232,7 @@ Index
`kind`:idx: `kind`:idx:
* `parsexml.html#110 <parsexml.html#110>`_ * `parsexml.html#110 <parsexml.html#110>`_
* `macros.html#121 <macros.html#121>`_ * `macros.html#122 <macros.html#122>`_
`l-values`:idx: `l-values`:idx:
`manual.html#107 <manual.html#107>`_ `manual.html#107 <manual.html#107>`_
@ -2245,13 +2251,13 @@ Index
* `system.html#172 <system.html#172>`_ * `system.html#172 <system.html#172>`_
* `strtabs.html#109 <strtabs.html#109>`_ * `strtabs.html#109 <strtabs.html#109>`_
* `parsesql.html#107 <parsesql.html#107>`_ * `parsesql.html#107 <parsesql.html#107>`_
* `macros.html#117 <macros.html#117>`_ * `macros.html#118 <macros.html#118>`_
`Letters`:idx: `Letters`:idx:
`strutils.html#103 <strutils.html#103>`_ `strutils.html#103 <strutils.html#103>`_
`letters`:idx: `letters`:idx:
`pegs.html#124 <pegs.html#124>`_ `pegs.html#125 <pegs.html#125>`_
`li`:idx: `li`:idx:
`xmlgen.html#148 <xmlgen.html#148>`_ `xmlgen.html#148 <xmlgen.html#148>`_
@ -2353,16 +2359,16 @@ Index
`xmlgen.html#150 <xmlgen.html#150>`_ `xmlgen.html#150 <xmlgen.html#150>`_
`match`:idx: `match`:idx:
* `regexprs.html#103 <regexprs.html#103>`_ * `regexprs.html#106 <regexprs.html#106>`_
* `regexprs.html#104 <regexprs.html#104>`_ * `regexprs.html#107 <regexprs.html#107>`_
* `pegs.html#132 <pegs.html#132>`_
* `pegs.html#133 <pegs.html#133>`_
`matchLen`:idx:
* `regexprs.html#105 <regexprs.html#105>`_
* `pegs.html#134 <pegs.html#134>`_ * `pegs.html#134 <pegs.html#134>`_
* `pegs.html#135 <pegs.html#135>`_ * `pegs.html#135 <pegs.html#135>`_
`matchLen`:idx:
* `regexprs.html#108 <regexprs.html#108>`_
* `pegs.html#136 <pegs.html#136>`_
* `pegs.html#137 <pegs.html#137>`_
`max`:idx: `max`:idx:
* `system.html#318 <system.html#318>`_ * `system.html#318 <system.html#318>`_
* `system.html#444 <system.html#444>`_ * `system.html#444 <system.html#444>`_
@ -2397,8 +2403,8 @@ Index
`mysql.html#191 <mysql.html#191>`_ `mysql.html#191 <mysql.html#191>`_
`MaxSubpatterns`:idx: `MaxSubpatterns`:idx:
* `regexprs.html#102 <regexprs.html#102>`_ * `regexprs.html#105 <regexprs.html#105>`_
* `pegs.html#131 <pegs.html#131>`_ * `pegs.html#132 <pegs.html#132>`_
`MAX_TINYINT_WIDTH`:idx: `MAX_TINYINT_WIDTH`:idx:
`mysql.html#190 <mysql.html#190>`_ `mysql.html#190 <mysql.html#190>`_
@ -2990,13 +2996,13 @@ Index
`system.html#134 <system.html#134>`_ `system.html#134 <system.html#134>`_
`natural`:idx: `natural`:idx:
`pegs.html#130 <pegs.html#130>`_ `pegs.html#131 <pegs.html#131>`_
`neginf`:idx: `neginf`:idx:
`system.html#430 <system.html#430>`_ `system.html#430 <system.html#430>`_
`nestList`:idx: `nestList`:idx:
`macros.html#151 <macros.html#151>`_ `macros.html#152 <macros.html#152>`_
`NET`:idx: `NET`:idx:
`mysql.html#199 <mysql.html#199>`_ `mysql.html#199 <mysql.html#199>`_
@ -3042,38 +3048,38 @@ Index
* `system.html#125 <system.html#125>`_ * `system.html#125 <system.html#125>`_
`newCall`:idx: `newCall`:idx:
* `macros.html#149 <macros.html#149>`_
* `macros.html#150 <macros.html#150>`_ * `macros.html#150 <macros.html#150>`_
* `macros.html#151 <macros.html#151>`_
`newFileStream`:idx: `newFileStream`:idx:
* `streams.html#120 <streams.html#120>`_ * `streams.html#120 <streams.html#120>`_
* `streams.html#121 <streams.html#121>`_ * `streams.html#121 <streams.html#121>`_
`newFloatLitNode`:idx: `newFloatLitNode`:idx:
`macros.html#142 <macros.html#142>`_ `macros.html#143 <macros.html#143>`_
`newIdentNode`:idx: `newIdentNode`:idx:
* `macros.html#143 <macros.html#143>`_
* `macros.html#144 <macros.html#144>`_ * `macros.html#144 <macros.html#144>`_
* `macros.html#145 <macros.html#145>`_
`newIntLitNode`:idx: `newIntLitNode`:idx:
`macros.html#141 <macros.html#141>`_ `macros.html#142 <macros.html#142>`_
`newLine`:idx:
`pegs.html#121 <pegs.html#121>`_
`newline`:idx: `newline`:idx:
* `manual.html#121 <manual.html#121>`_ * `manual.html#121 <manual.html#121>`_
* `pegs.html#119 <pegs.html#119>`_ * `pegs.html#120 <pegs.html#120>`_
`newLine`:idx:
`pegs.html#120 <pegs.html#120>`_
`NewLines`:idx: `NewLines`:idx:
`lexbase.html#102 <lexbase.html#102>`_ `lexbase.html#102 <lexbase.html#102>`_
`newNimNode`:idx: `newNimNode`:idx:
`macros.html#134 <macros.html#134>`_ `macros.html#135 <macros.html#135>`_
`newNonTerminal`:idx: `newNonTerminal`:idx:
`pegs.html#123 <pegs.html#123>`_ `pegs.html#124 <pegs.html#124>`_
`newSeq`:idx: `newSeq`:idx:
`system.html#167 <system.html#167>`_ `system.html#167 <system.html#167>`_
@ -3089,7 +3095,7 @@ Index
* `strtabs.html#105 <strtabs.html#105>`_ * `strtabs.html#105 <strtabs.html#105>`_
`newStrLitNode`:idx: `newStrLitNode`:idx:
`macros.html#140 <macros.html#140>`_ `macros.html#141 <macros.html#141>`_
`next`:idx: `next`:idx:
* `parseopt.html#105 <parseopt.html#105>`_ * `parseopt.html#105 <parseopt.html#105>`_
@ -3124,7 +3130,7 @@ Index
`mysql.html#136 <mysql.html#136>`_ `mysql.html#136 <mysql.html#136>`_
`nonterminal`:idx: `nonterminal`:idx:
`pegs.html#122 <pegs.html#122>`_ `pegs.html#123 <pegs.html#123>`_
`normalize`:idx: `normalize`:idx:
`strutils.html#118 <strutils.html#118>`_ `strutils.html#118 <strutils.html#118>`_
@ -3238,7 +3244,7 @@ Index
`strtabs.html#110 <strtabs.html#110>`_ `strtabs.html#110 <strtabs.html#110>`_
`parallelReplace`:idx: `parallelReplace`:idx:
`pegs.html#144 <pegs.html#144>`_ `pegs.html#146 <pegs.html#146>`_
`param`:idx: `param`:idx:
`xmlgen.html#158 <xmlgen.html#158>`_ `xmlgen.html#158 <xmlgen.html#158>`_
@ -3268,7 +3274,7 @@ Index
`strutils.html#142 <strutils.html#142>`_ `strutils.html#142 <strutils.html#142>`_
`parsePeg`:idx: `parsePeg`:idx:
`pegs.html#150 <pegs.html#150>`_ `pegs.html#151 <pegs.html#151>`_
`parseSQL`:idx: `parseSQL`:idx:
`parsesql.html#109 <parsesql.html#109>`_ `parsesql.html#109 <parsesql.html#109>`_
@ -3403,7 +3409,7 @@ Index
`libcurl.html#122 <libcurl.html#122>`_ `libcurl.html#122 <libcurl.html#122>`_
`peg`:idx: `peg`:idx:
`pegs.html#151 <pegs.html#151>`_ `pegs.html#152 <pegs.html#152>`_
`Pfd_set`:idx: `Pfd_set`:idx:
`libcurl.html#138 <libcurl.html#138>`_ `libcurl.html#138 <libcurl.html#138>`_
@ -3771,16 +3777,16 @@ Index
`system.html#412 <system.html#412>`_ `system.html#412 <system.html#412>`_
`reBinary`:idx: `reBinary`:idx:
`regexprs.html#113 <regexprs.html#113>`_ `regexprs.html#116 <regexprs.html#116>`_
`Recursive module dependancies`:idx: `Recursive module dependancies`:idx:
`manual.html#221 <manual.html#221>`_ `manual.html#221 <manual.html#221>`_
`reEmail`:idx: `reEmail`:idx:
`regexprs.html#116 <regexprs.html#116>`_ `regexprs.html#119 <regexprs.html#119>`_
`reFloat`:idx: `reFloat`:idx:
`regexprs.html#115 <regexprs.html#115>`_ `regexprs.html#118 <regexprs.html#118>`_
`REFRESH_DES_KEY_FILE`:idx: `REFRESH_DES_KEY_FILE`:idx:
`mysql.html#154 <mysql.html#154>`_ `mysql.html#154 <mysql.html#154>`_
@ -3828,13 +3834,13 @@ Index
`nimrodc.html#112 <nimrodc.html#112>`_ `nimrodc.html#112 <nimrodc.html#112>`_
`reHex`:idx: `reHex`:idx:
`regexprs.html#112 <regexprs.html#112>`_ `regexprs.html#115 <regexprs.html#115>`_
`reIdentifier`:idx: `reIdentifier`:idx:
`regexprs.html#109 <regexprs.html#109>`_ `regexprs.html#112 <regexprs.html#112>`_
`reInteger`:idx: `reInteger`:idx:
`regexprs.html#111 <regexprs.html#111>`_ `regexprs.html#114 <regexprs.html#114>`_
`removeDir`:idx: `removeDir`:idx:
`os.html#158 <os.html#158>`_ `os.html#158 <os.html#158>`_
@ -3843,13 +3849,13 @@ Index
`os.html#144 <os.html#144>`_ `os.html#144 <os.html#144>`_
`reNatural`:idx: `reNatural`:idx:
`regexprs.html#110 <regexprs.html#110>`_ `regexprs.html#113 <regexprs.html#113>`_
`renderSQL`:idx: `renderSQL`:idx:
`parsesql.html#110 <parsesql.html#110>`_ `parsesql.html#110 <parsesql.html#110>`_
`reOctal`:idx: `reOctal`:idx:
`regexprs.html#114 <regexprs.html#114>`_ `regexprs.html#117 <regexprs.html#117>`_
`repeatChar`:idx: `repeatChar`:idx:
`strutils.html#146 <strutils.html#146>`_ `strutils.html#146 <strutils.html#146>`_
@ -3857,7 +3863,7 @@ Index
`replace`:idx: `replace`:idx:
* `strutils.html#154 <strutils.html#154>`_ * `strutils.html#154 <strutils.html#154>`_
* `strutils.html#155 <strutils.html#155>`_ * `strutils.html#155 <strutils.html#155>`_
* `pegs.html#143 <pegs.html#143>`_ * `pegs.html#145 <pegs.html#145>`_
`replaceStr`:idx: `replaceStr`:idx:
* `strutils.html#122 <strutils.html#122>`_ * `strutils.html#122 <strutils.html#122>`_
@ -3880,7 +3886,7 @@ Index
`manual.html#192 <manual.html#192>`_ `manual.html#192 <manual.html#192>`_
`reURL`:idx: `reURL`:idx:
`regexprs.html#117 <regexprs.html#117>`_ `regexprs.html#120 <regexprs.html#120>`_
`round`:idx: `round`:idx:
`math.html#121 <math.html#121>`_ `math.html#121 <math.html#121>`_
@ -4048,6 +4054,9 @@ Index
* `system.html#230 <system.html#230>`_ * `system.html#230 <system.html#230>`_
* `system.html#231 <system.html#231>`_ * `system.html#231 <system.html#231>`_
`simple assertions`:idx:
`regexprs.html#103 <regexprs.html#103>`_
`simple statements`:idx: `simple statements`:idx:
`manual.html#177 <manual.html#177>`_ `manual.html#177 <manual.html#177>`_
@ -4074,8 +4083,8 @@ Index
* `strutils.html#127 <strutils.html#127>`_ * `strutils.html#127 <strutils.html#127>`_
* `strutils.html#133 <strutils.html#133>`_ * `strutils.html#133 <strutils.html#133>`_
* `strutils.html#134 <strutils.html#134>`_ * `strutils.html#134 <strutils.html#134>`_
* `pegs.html#146 <pegs.html#146>`_ * `pegs.html#148 <pegs.html#148>`_
* `pegs.html#147 <pegs.html#147>`_ * `pegs.html#149 <pegs.html#149>`_
`splitFile`:idx: `splitFile`:idx:
`os.html#129 <os.html#129>`_ `os.html#129 <os.html#129>`_
@ -4611,7 +4620,7 @@ Index
`startsWith`:idx: `startsWith`:idx:
* `strutils.html#147 <strutils.html#147>`_ * `strutils.html#147 <strutils.html#147>`_
* `pegs.html#141 <pegs.html#141>`_ * `pegs.html#143 <pegs.html#143>`_
`statement macros`:idx: `statement macros`:idx:
`tut2.html#112 <tut2.html#112>`_ `tut2.html#112 <tut2.html#112>`_
@ -4702,10 +4711,10 @@ Index
`manual.html#152 <manual.html#152>`_ `manual.html#152 <manual.html#152>`_
`strVal`:idx: `strVal`:idx:
`macros.html#127 <macros.html#127>`_ `macros.html#128 <macros.html#128>`_
`strVal=`:idx: `strVal=`:idx:
`macros.html#133 <macros.html#133>`_ `macros.html#134 <macros.html#134>`_
`st_udf_args`:idx: `st_udf_args`:idx:
`mysql.html#258 <mysql.html#258>`_ `mysql.html#258 <mysql.html#258>`_
@ -4751,10 +4760,10 @@ Index
`dynlib.html#104 <dynlib.html#104>`_ `dynlib.html#104 <dynlib.html#104>`_
`symbol`:idx: `symbol`:idx:
`macros.html#124 <macros.html#124>`_ `macros.html#125 <macros.html#125>`_
`symbol=`:idx: `symbol=`:idx:
`macros.html#130 <macros.html#130>`_ `macros.html#131 <macros.html#131>`_
`syscall`:idx: `syscall`:idx:
`manual.html#172 <manual.html#172>`_ `manual.html#172 <manual.html#172>`_
@ -5114,7 +5123,7 @@ Index
`strutils.html#145 <strutils.html#145>`_ `strutils.html#145 <strutils.html#145>`_
`toStrLit`:idx: `toStrLit`:idx:
`macros.html#145 <macros.html#145>`_ `macros.html#146 <macros.html#146>`_
`toTitle`:idx: `toTitle`:idx:
`unicode.html#113 <unicode.html#113>`_ `unicode.html#113 <unicode.html#113>`_
@ -5153,7 +5162,7 @@ Index
* `tut1.html#121 <tut1.html#121>`_ * `tut1.html#121 <tut1.html#121>`_
`transformFile`:idx: `transformFile`:idx:
`pegs.html#145 <pegs.html#145>`_ `pegs.html#147 <pegs.html#147>`_
`TRequestMethod`:idx: `TRequestMethod`:idx:
`cgi.html#105 <cgi.html#105>`_ `cgi.html#105 <cgi.html#105>`_
@ -5244,10 +5253,10 @@ Index
`parsexml.html#106 <parsexml.html#106>`_ `parsexml.html#106 <parsexml.html#106>`_
`typ`:idx: `typ`:idx:
`macros.html#126 <macros.html#126>`_ `macros.html#127 <macros.html#127>`_
`typ=`:idx: `typ=`:idx:
`macros.html#132 <macros.html#132>`_ `macros.html#133 <macros.html#133>`_
`type`:idx: `type`:idx:
* `manual.html#102 <manual.html#102>`_ * `manual.html#102 <manual.html#102>`_
@ -5363,7 +5372,7 @@ Index
* `tut2.html#103 <tut2.html#103>`_ * `tut2.html#103 <tut2.html#103>`_
`verbose`:idx: `verbose`:idx:
`regexprs.html#118 <regexprs.html#118>`_ `regexprs.html#121 <regexprs.html#121>`_
`vertical tabulator`:idx: `vertical tabulator`:idx:
`manual.html#126 <manual.html#126>`_ `manual.html#126 <manual.html#126>`_
@ -5387,7 +5396,7 @@ Index
`warning`:idx: `warning`:idx:
* `manual.html#225 <manual.html#225>`_ * `manual.html#225 <manual.html#225>`_
* `manual.html#232 <manual.html#232>`_ * `manual.html#232 <manual.html#232>`_
* `macros.html#138 <macros.html#138>`_ * `macros.html#139 <macros.html#139>`_
`when`:idx: `when`:idx:
* `manual.html#185 <manual.html#185>`_ * `manual.html#185 <manual.html#185>`_
@ -5400,7 +5409,7 @@ Index
`strutils.html#102 <strutils.html#102>`_ `strutils.html#102 <strutils.html#102>`_
`whitespace`:idx: `whitespace`:idx:
`pegs.html#126 <pegs.html#126>`_ `pegs.html#127 <pegs.html#127>`_
`winTimeToUnixTime`:idx: `winTimeToUnixTime`:idx:
`times.html#118 <times.html#118>`_ `times.html#118 <times.html#118>`_

View file

@ -42,7 +42,7 @@ type
pkSequence, ## a b c ... --> Internal DSL: peg(a, b, c) pkSequence, ## a b c ... --> Internal DSL: peg(a, b, c)
pkOrderedChoice, ## a / b / ... --> Internal DSL: a / b or /[a, b, c] pkOrderedChoice, ## a / b / ... --> Internal DSL: a / b or /[a, b, c]
pkGreedyRep, ## a* --> Internal DSL: *a pkGreedyRep, ## a* --> Internal DSL: *a
## a+ --> Internal DSL: +a; represented as (a a*) ## a+ --> (a a*)
pkGreedyRepChar, ## x* where x is a single character (superop) pkGreedyRepChar, ## x* where x is a single character (superop)
pkGreedyRepSet, ## [set]* (superop) pkGreedyRepSet, ## [set]* (superop)
pkGreedyAny, ## .* or _* (superop) pkGreedyAny, ## .* or _* (superop)
@ -50,6 +50,7 @@ type
pkAndPredicate, ## &a --> Internal DSL: &a pkAndPredicate, ## &a --> Internal DSL: &a
pkNotPredicate, ## !a --> Internal DSL: !a pkNotPredicate, ## !a --> Internal DSL: !a
pkCapture, ## {a} --> Internal DSL: capture(a) pkCapture, ## {a} --> Internal DSL: capture(a)
pkSearch, ## @a --> Internal DSL: @a
pkRule, ## a <- b pkRule, ## a <- b
pkList ## a, b pkList ## a, b
TNonTerminalFlag = enum TNonTerminalFlag = enum
@ -174,7 +175,24 @@ proc `*`*(a: TPeg): TPeg =
else: else:
result.kind = pkGreedyRep result.kind = pkGreedyRep
result.sons = @[a] result.sons = @[a]
proc `@`*(a: TPeg): TPeg =
## constructs a "search" for the PEG `a`
result.kind = pkSearch
result.sons = @[a]
when false:
proc contains(a: TPeg, k: TPegKind): bool =
if a.kind == k: return true
case a.kind
of pkEmpty, pkAny, pkAnyRune, pkGreedyAny, pkNewLine, pkTerminal,
pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar, pkGreedyRepChar,
pkCharChoice, pkGreedyRepSet: nil
of pkNonTerminal: return true
else:
for i in 0..a.sons.len-1:
if contains(a.sons[i], k): return true
proc `+`*(a: TPeg): TPeg = proc `+`*(a: TPeg): TPeg =
## constructs a "greedy positive repetition" with the PEG `a` ## constructs a "greedy positive repetition" with the PEG `a`
return sequence(a, *a) return sequence(a, *a)
@ -271,6 +289,125 @@ const
MaxSubpatterns* = 10 ## defines the maximum number of subpatterns that MaxSubpatterns* = 10 ## defines the maximum number of subpatterns that
## can be captured. More subpatterns cannot be captured! ## can be captured. More subpatterns cannot be captured!
# ------------------------- debugging -----------------------------------------
proc esc(c: char, reserved = {'\0'..'\255'}): string =
case c
of '\b': result = "\\b"
of '\t': result = "\\t"
of '\c': result = "\\c"
of '\L': result = "\\l"
of '\v': result = "\\v"
of '\f': result = "\\f"
of '\e': result = "\\e"
of '\a': result = "\\a"
of '\\': result = "\\\\"
of 'a'..'z', 'A'..'Z', '0'..'9', '_': result = $c
elif c < ' ' or c >= '\128': result = '\\' & $ord(c)
elif c in reserved: result = '\\' & c
else: result = $c
proc singleQuoteEsc(c: Char): string = return "'" & esc(c, {'\''}) & "'"
proc singleQuoteEsc(str: string): string =
result = "'"
for c in items(str): add result, esc(c, {'\''})
add result, '\''
proc charSetEscAux(cc: set[char]): string =
const reserved = {'^', '-', ']'}
result = ""
var c1 = 0
while c1 <= 0xff:
if chr(c1) in cc:
var c2 = c1
while c2 < 0xff and chr(succ(c2)) in cc: inc(c2)
if c1 == c2:
add result, esc(chr(c1), reserved)
elif c2 == succ(c1):
add result, esc(chr(c1), reserved) & esc(chr(c2), reserved)
else:
add result, esc(chr(c1), reserved) & '-' & esc(chr(c2), reserved)
c1 = c2
inc(c1)
proc CharSetEsc(cc: set[char]): string =
if card(cc) >= 128+64:
result = "[^" & CharSetEscAux({'\1'..'\xFF'} - cc) & ']'
else:
result = '[' & CharSetEscAux(cc) & ']'
proc toStrAux(r: TPeg, res: var string) =
case r.kind
of pkEmpty: add(res, "()")
of pkAny: add(res, '.')
of pkAnyRune: add(res, '_')
of pkNewline: add(res, "\\n")
of pkTerminal: add(res, singleQuoteEsc(r.term))
of pkTerminalIgnoreCase:
add(res, 'i')
add(res, singleQuoteEsc(r.term))
of pkTerminalIgnoreStyle:
add(res, 'y')
add(res, singleQuoteEsc(r.term))
of pkChar: add(res, singleQuoteEsc(r.ch))
of pkCharChoice: add(res, charSetEsc(r.charChoice^))
of pkNonTerminal: add(res, r.nt.name)
of pkSequence:
add(res, '(')
toStrAux(r.sons[0], res)
for i in 1 .. high(r.sons):
add(res, ' ')
toStrAux(r.sons[i], res)
add(res, ')')
of pkOrderedChoice:
add(res, '(')
toStrAux(r.sons[0], res)
for i in 1 .. high(r.sons):
add(res, " / ")
toStrAux(r.sons[i], res)
add(res, ')')
of pkGreedyRep:
toStrAux(r.sons[0], res)
add(res, '*')
of pkGreedyRepChar:
add(res, singleQuoteEsc(r.ch))
add(res, '*')
of pkGreedyRepSet:
add(res, charSetEsc(r.charChoice^))
add(res, '*')
of pkGreedyAny:
add(res, ".*")
of pkOption:
toStrAux(r.sons[0], res)
add(res, '?')
of pkAndPredicate:
add(res, '&')
toStrAux(r.sons[0], res)
of pkNotPredicate:
add(res, '!')
toStrAux(r.sons[0], res)
of pkSearch:
add(res, '@')
toStrAux(r.sons[0], res)
of pkCapture:
add(res, '{')
toStrAux(r.sons[0], res)
add(res, '}')
of pkRule:
toStrAux(r.sons[0], res)
add(res, " <- ")
toStrAux(r.sons[1], res)
of pkList:
for i in 0 .. high(r.sons):
toStrAux(r.sons[i], res)
add(res, "\n")
proc `$` *(r: TPeg): string =
## converts a PEG to its string representation
result = ""
toStrAux(r, result)
# --------------------- core engine ------------------------------------------- # --------------------- core engine -------------------------------------------
type type
@ -370,6 +507,17 @@ proc m(s: string, p: TPeg, start: int, c: var TMatchClosure): int =
result = m(s, p.sons[i], start, c) result = m(s, p.sons[i], start, c)
if result >= 0: break if result >= 0: break
c.ml = oldMl c.ml = oldMl
of pkSearch:
var oldMl = c.ml
result = 0
while start+result < s.len:
var x = m(s, p.sons[0], start+result, c)
if x >= 0:
inc(result, x)
return
inc(result)
result = -1
c.ml = oldMl
of pkGreedyRep: of pkGreedyRep:
result = 0 result = 0
while true: while true:
@ -607,123 +755,6 @@ proc split*(s: string, sep: TPeg): seq[string] {.noSideEffect.} =
## Splits the string `s` into substrings. ## Splits the string `s` into substrings.
accumulateResult(split(s, sep)) accumulateResult(split(s, sep))
# ------------------------- debugging -----------------------------------------
proc esc(c: char, reserved = {'\0'..'\255'}): string =
case c
of '\b': result = "\\b"
of '\t': result = "\\t"
of '\c': result = "\\c"
of '\L': result = "\\l"
of '\v': result = "\\v"
of '\f': result = "\\f"
of '\e': result = "\\e"
of '\a': result = "\\a"
of '\\': result = "\\\\"
of 'a'..'z', 'A'..'Z', '0'..'9', '_': result = $c
elif c < ' ' or c >= '\128': result = '\\' & $ord(c)
elif c in reserved: result = '\\' & c
else: result = $c
proc singleQuoteEsc(c: Char): string = return "'" & esc(c, {'\''}) & "'"
proc singleQuoteEsc(str: string): string =
result = "'"
for c in items(str): add result, esc(c, {'\''})
add result, '\''
proc charSetEscAux(cc: set[char]): string =
const reserved = {'^', '-', ']'}
result = ""
var c1 = 0
while c1 <= 0xff:
if chr(c1) in cc:
var c2 = c1
while c2 < 0xff and chr(succ(c2)) in cc: inc(c2)
if c1 == c2:
add result, esc(chr(c1), reserved)
elif c2 == succ(c1):
add result, esc(chr(c1), reserved) & esc(chr(c2), reserved)
else:
add result, esc(chr(c1), reserved) & '-' & esc(chr(c2), reserved)
c1 = c2
inc(c1)
proc CharSetEsc(cc: set[char]): string =
if card(cc) >= 128+64:
result = "[^" & CharSetEscAux({'\1'..'\xFF'} - cc) & ']'
else:
result = '[' & CharSetEscAux(cc) & ']'
proc toStrAux(r: TPeg, res: var string) =
case r.kind
of pkEmpty: add(res, "()")
of pkAny: add(res, '.')
of pkAnyRune: add(res, '_')
of pkNewline: add(res, "\\n")
of pkTerminal: add(res, singleQuoteEsc(r.term))
of pkTerminalIgnoreCase:
add(res, 'i')
add(res, singleQuoteEsc(r.term))
of pkTerminalIgnoreStyle:
add(res, 'y')
add(res, singleQuoteEsc(r.term))
of pkChar: add(res, singleQuoteEsc(r.ch))
of pkCharChoice: add(res, charSetEsc(r.charChoice^))
of pkNonTerminal: add(res, r.nt.name)
of pkSequence:
add(res, '(')
toStrAux(r.sons[0], res)
for i in 1 .. high(r.sons):
add(res, ' ')
toStrAux(r.sons[i], res)
add(res, ')')
of pkOrderedChoice:
add(res, '(')
toStrAux(r.sons[0], res)
for i in 1 .. high(r.sons):
add(res, " / ")
toStrAux(r.sons[i], res)
add(res, ')')
of pkGreedyRep:
toStrAux(r.sons[0], res)
add(res, '*')
of pkGreedyRepChar:
add(res, singleQuoteEsc(r.ch))
add(res, '*')
of pkGreedyRepSet:
add(res, charSetEsc(r.charChoice^))
add(res, '*')
of pkGreedyAny:
add(res, ".*")
of pkOption:
toStrAux(r.sons[0], res)
add(res, '?')
of pkAndPredicate:
add(res, '&')
toStrAux(r.sons[0], res)
of pkNotPredicate:
add(res, '!')
toStrAux(r.sons[0], res)
of pkCapture:
add(res, '{')
toStrAux(r.sons[0], res)
add(res, '}')
of pkRule:
toStrAux(r.sons[0], res)
add(res, " <- ")
toStrAux(r.sons[1], res)
of pkList:
for i in 0 .. high(r.sons):
toStrAux(r.sons[i], res)
add(res, "\n")
proc `$` *(r: TPeg): string =
## converts a PEG to its string representation
result = ""
toStrAux(r, result)
# ------------------- scanner ------------------------------------------------- # ------------------- scanner -------------------------------------------------
type type
@ -751,6 +782,7 @@ type
tkAmp, ## '&' tkAmp, ## '&'
tkNot, ## '!' tkNot, ## '!'
tkOption, ## '?' tkOption, ## '?'
tkAt, ## '@'
tkBuiltin, ## \identifier tkBuiltin, ## \identifier
tkEscaped ## \\ tkEscaped ## \\
@ -772,7 +804,7 @@ const
tokKindToStr: array[TTokKind, string] = [ tokKindToStr: array[TTokKind, string] = [
"invalid", "[EOF]", ".", "_", "identifier", "string literal", "invalid", "[EOF]", ".", "_", "identifier", "string literal",
"character set", "(", ")", "{", "}", "<-", "/", "*", "+", "&", "!", "?", "character set", "(", ")", "{", "}", "<-", "/", "*", "+", "&", "!", "?",
"built-in", "escaped" "@", "built-in", "escaped"
] ]
proc HandleCR(L: var TPegLexer, pos: int): int = proc HandleCR(L: var TPegLexer, pos: int): int =
@ -1063,6 +1095,10 @@ proc getTok(c: var TPegLexer, tok: var TToken) =
tok.kind = tkAmp tok.kind = tkAmp
inc(c.bufpos) inc(c.bufpos)
add(tok.literal, '!') add(tok.literal, '!')
of '@':
tok.kind = tkAt
inc(c.bufpos)
add(tok.literal, '@')
else: else:
add(tok.literal, c.buf[c.bufpos]) add(tok.literal, c.buf[c.bufpos])
inc(c.bufpos) inc(c.bufpos)
@ -1118,6 +1154,9 @@ proc primary(p: var TPegParser): TPeg =
of tkNot: of tkNot:
getTok(p) getTok(p)
return !primary(p) return !primary(p)
of tkAt:
getTok(p)
return @primary(p)
else: nil else: nil
case p.tok.kind case p.tok.kind
of tkIdentifier: of tkIdentifier:
@ -1187,7 +1226,7 @@ proc seqExpr(p: var TPegParser): TPeg =
result = primary(p) result = primary(p)
while true: while true:
case p.tok.kind case p.tok.kind
of tkAmp, tkNot, tkStringLit, tkCharset, tkParLe, tkCurlyLe, of tkAmp, tkNot, tkAt, tkStringLit, tkCharset, tkParLe, tkCurlyLe,
tkAny, tkAnyRune, tkBuiltin, tkEscaped: tkAny, tkAnyRune, tkBuiltin, tkEscaped:
result = sequence(result, primary(p)) result = sequence(result, primary(p))
of tkIdentifier: of tkIdentifier:
@ -1261,6 +1300,7 @@ proc peg*(pattern: string): TPeg =
result = parsePeg(pattern, "pattern") result = parsePeg(pattern, "pattern")
when isMainModule: when isMainModule:
assert match("(a b c)", peg"'(' @ ')'")
assert match("W_HI_Le", peg"\y 'while'") assert match("W_HI_Le", peg"\y 'while'")
assert(not match("W_HI_L", peg"\y 'while'")) assert(not match("W_HI_L", peg"\y 'while'"))
assert(not match("W_HI_Le", peg"\y v'while'")) assert(not match("W_HI_Le", peg"\y v'while'"))
@ -1315,6 +1355,11 @@ when isMainModule:
""" """
assert($g2 == "((A B) / (C D))") assert($g2 == "((A B) / (C D))")
assert match("cccccdddddd", g2) assert match("cccccdddddd", g2)
echo "var1=key; var2=key2".replace(peg"{\ident}'='{\ident}", "$1<-$2$2") assert("var1=key; var2=key2".replace(peg"{\ident}'='{\ident}", "$1<-$2$2") ==
"var1<-keykey; var2<-key2key2")
assert "var1=key; var2=key2".endsWith(peg"{\ident}'='{\ident}") assert "var1=key; var2=key2".endsWith(peg"{\ident}'='{\ident}")
if "aaaaaa" =~ peg"'aa' !. / ({'a'})+":
assert matches[0] == "a"
else:
assert false

View file

@ -44,15 +44,13 @@ proc runeLenAt*(s: string, i: int): int =
template fastRuneAt*(s: string, i: int, result: expr, doInc = true) = template fastRuneAt*(s: string, i: int, result: expr, doInc = true) =
## Returns the unicode character ``s[i]`` in `result`. If ``doInc == true`` ## Returns the unicode character ``s[i]`` in `result`. If ``doInc == true``
## `i` is incremented by the number of bytes that have been processed. ## `i` is incremented by the number of bytes that have been processed.
when not defined(ones):
template ones(n: expr): expr = ((1 shl n)-1)
if ord(s[i]) <=% 127: if ord(s[i]) <=% 127:
result = TRune(ord(s[i])) result = TRune(ord(s[i]))
when doInc: inc(i) when doInc: inc(i)
elif ord(s[i]) shr 5 == 0b110: elif ord(s[i]) shr 5 == 0b110:
assert(ord(s[i+1]) shr 6 == 0b10) assert(ord(s[i+1]) shr 6 == 0b10)
result = TRune((ord(s[i]) and ones(5)) shl 6 or (ord(s[i+1]) and ones(6))) result = TRune((ord(s[i]) and (bind ones(5))) shl 6 or
(ord(s[i+1]) and ones(6)))
when doInc: inc(i, 2) when doInc: inc(i, 2)
elif ord(s[i]) shr 4 == 0b1110: elif ord(s[i]) shr 4 == 0b1110:
assert(ord(s[i+1]) shr 6 == 0b10) assert(ord(s[i+1]) shr 6 == 0b10)

139
nim/llvmdata.pas Executable file
View file

@ -0,0 +1,139 @@
//
//
// The Nimrod Compiler
// (c) Copyright 2009 Andreas Rumpf
//
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
unit llvmdata;
// this module implements data structures for emitting LLVM.
interface
{$include 'config.inc'}
uses
nsystem, ast, astalgo, idents, lists, passes;
type
VTypeKind = (
VoidTyID, ///< 0: type with no size
FloatTyID, ///< 1: 32 bit floating point type
DoubleTyID, ///< 2: 64 bit floating point type
X86_FP80TyID, ///< 3: 80 bit floating point type (X87)
FP128TyID, ///< 4: 128 bit floating point type (112-bit mantissa)
PPC_FP128TyID, ///< 5: 128 bit floating point type (two 64-bits)
LabelTyID, ///< 6: Labels
MetadataTyID, ///< 7: Metadata
// Derived types... see DerivedTypes.h file...
// Make sure FirstDerivedTyID stays up to date!!!
IntegerTyID, ///< 8: Arbitrary bit width integers
FunctionTyID, ///< 9: Functions
StructTyID, ///< 10: Structures
ArrayTyID, ///< 11: Arrays
PointerTyID, ///< 12: Pointers
OpaqueTyID, ///< 13: Opaque: type with unknown structure
VectorTyID, ///< 14: SIMD 'packed' format, or other vector type
);
VType = ^VTypeDesc;
VTypeSeq = array of VType;
VTypeDesc = object(TIdObj)
k: VTypeKind;
s: VTypeSeq;
arrayLen: int;
name: string;
end;
VInstrKind = (
iNone,
iAdd,
iSub,
iMul,
iDiv,
iMod,
);
VLocalVar = record
end;
VInstr = record
k: VInstrKind;
end;
/// This represents a single basic block in LLVM. A basic block is simply a
/// container of instructions that execute sequentially. Basic blocks are Values
/// because they are referenced by instructions such as branches and switch
/// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block
/// represents a label to which a branch can jump.
///
VBlock = ^VBlockDesc;
VBlockDesc = record // LLVM basic block
// list of instructions
end;
VLinkage = (
ExternalLinkage, // Externally visible function
LinkOnceLinkage, // Keep one copy of function when linking (inline)
WeakLinkage, // Keep one copy of function when linking (weak)
AppendingLinkage, // Special purpose, only applies to global arrays
InternalLinkage, // Rename collisions when linking (static functions)
DLLImportLinkage, // Function to be imported from DLL
DLLExportLinkage, // Function to be accessible from DLL
ExternalWeakLinkage, // ExternalWeak linkage description
GhostLinkage // Stand-in functions for streaming fns from bitcode
);
VVisibility = (
DefaultVisibility, // The GV is visible
HiddenVisibility, // The GV is hidden
ProtectedVisibility // The GV is protected
);
TLLVMCallConv = (
CCallConv = 0,
FastCallConv = 8,
ColdCallConv = 9,
X86StdcallCallConv = 64,
X86FastcallCallConv = 65
);
VProc = ^VProcDesc;
VProcDesc = record
b: VBlock;
name: string;
sym: PSym; // proc that is generated
linkage: VLinkage;
vis: VVisibility;
callConv: VCallConv;
next: VProc;
end;
VModule = ^VModuleDesc;
VModuleDesc = object(TPassContext) // represents a C source file
sym: PSym;
filename: string;
typeCache: TIdTable; // cache the generated types
forwTypeCache: TIdTable; // cache for forward declarations of types
declaredThings: TIntSet; // things we have declared in this file
declaredProtos: TIntSet; // prototypes we have declared in this file
headerFiles: TLinkedList; // needed headers to include
typeInfoMarker: TIntSet; // needed for generating type information
initProc: VProc; // code for init procedure
typeStack: TTypeSeq; // used for type generation
dataCache: TNodeTable;
forwardedProcs: TSymSeq; // keep forwarded procs here
typeNodes, nimTypes: int;// used for type info generation
typeNodesName, nimTypesName: PRope; // used for type info generation
labels: natural; // for generating unique module-scope names
next: VModule; // to stack modules
end;
implementation
end.

View file

@ -146,8 +146,7 @@ begin
end; end;
end; end;
procedure qualifiedIdentListAux(var p: TParser; endTok: TTokType; procedure qualifiedIdentListAux(var p: TParser; endTok: TTokType; result: PNode);
result: PNode);
var var
a: PNode; a: PNode;
begin begin
@ -216,16 +215,6 @@ begin
eat(p, tkParRi); eat(p, tkParRi);
end; end;
procedure setBaseFlags(n: PNode; base: TNumericalBase);
begin
case base of
base10: begin end;
base2: include(n.flags, nfBase2);
base8: include(n.flags, nfBase8);
base16: include(n.flags, nfBase16);
end
end;
function identOrLiteral(var p: TParser): PNode; function identOrLiteral(var p: TParser): PNode;
begin begin
case p.tok.tokType of case p.tok.tokType of
@ -542,7 +531,7 @@ begin
optInd(p, result); optInd(p, result);
while (p.tok.tokType = tkSymbol) or (p.tok.tokType = tkAccent) do begin while (p.tok.tokType = tkSymbol) or (p.tok.tokType = tkAccent) do begin
a := parseIdentColonEquals(p, {@set}[]); a := parseIdentColonEquals(p, {@set}[]);
addSon(result, a); addSon(result, a);
if p.tok.tokType <> tkComma then break; if p.tok.tokType <> tkComma then break;
getTok(p); getTok(p);
optInd(p, a) optInd(p, a)
@ -729,12 +718,12 @@ begin
end end
end; end;
function parseImportStmt(var p: TParser): PNode; function parseImportOrIncludeStmt(var p: TParser; kind: TNodeKind): PNode;
var var
a: PNode; a: PNode;
begin begin
result := newNodeP(nkImportStmt, p); result := newNodeP(kind, p);
getTok(p); // skip `import` getTok(p); // skip `import` or `include`
optInd(p, result); optInd(p, result);
while true do begin while true do begin
case p.tok.tokType of case p.tok.tokType of
@ -764,41 +753,6 @@ begin
end; end;
end; end;
function parseIncludeStmt(var p: TParser): PNode;
var
a: PNode;
begin
result := newNodeP(nkIncludeStmt, p);
getTok(p); // skip `include`
optInd(p, result);
while true do begin
case p.tok.tokType of
tkEof, tkSad, tkDed: break;
tkSymbol, tkAccent: a := parseSymbol(p);
tkRStrLit: begin
a := newStrNodeP(nkRStrLit, p.tok.literal, p);
getTok(p)
end;
tkStrLit: begin
a := newStrNodeP(nkStrLit, p.tok.literal, p);
getTok(p);
end;
tkTripleStrLit: begin
a := newStrNodeP(nkTripleStrLit, p.tok.literal, p);
getTok(p)
end;
else begin
parMessage(p, errIdentifierExpected, tokToStr(p.tok));
break
end;
end;
addSon(result, a);
if p.tok.tokType <> tkComma then break;
getTok(p);
optInd(p, a)
end;
end;
function parseFromStmt(var p: TParser): PNode; function parseFromStmt(var p: TParser): PNode;
var var
a: PNode; a: PNode;
@ -1150,6 +1104,24 @@ begin
indAndComment(p, result); // XXX: special extension! indAndComment(p, result); // XXX: special extension!
end; end;
function parseConstSection(var p: TParser): PNode;
begin
result := newNodeP(nkConstSection, p);
getTok(p);
skipComment(p, result);
if p.tok.tokType = tkCurlyLe then begin
getTok(p);
skipComment(p, result);
while (p.tok.tokType <> tkCurlyRi) and (p.tok.tokType <> tkEof) do begin
addSon(result, parseConstant(p))
end;
eat(p, tkCurlyRi);
end
else
addSon(result, parseConstant(p));
end;
function parseEnum(var p: TParser): PNode; function parseEnum(var p: TParser): PNode;
var var
a, b: PNode; a, b: PNode;
@ -1379,9 +1351,9 @@ begin
tkBreak: result := parseBreakOrContinue(p, nkBreakStmt); tkBreak: result := parseBreakOrContinue(p, nkBreakStmt);
tkContinue: result := parseBreakOrContinue(p, nkContinueStmt); tkContinue: result := parseBreakOrContinue(p, nkContinueStmt);
tkCurlyDotLe: result := parsePragma(p); tkCurlyDotLe: result := parsePragma(p);
tkImport: result := parseImportStmt(p); tkImport: result := parseImportOrIncludeStmt(p, nkImportStmt);
tkFrom: result := parseFromStmt(p); tkFrom: result := parseFromStmt(p);
tkInclude: result := parseIncludeStmt(p); tkInclude: result := parseImportOrIncludeStmt(p, nkIncludeStmt);
tkComment: result := newCommentStmt(p); tkComment: result := newCommentStmt(p);
else begin else begin
if isExprStart(p) then if isExprStart(p) then
@ -1394,6 +1366,24 @@ begin
skipComment(p, result); skipComment(p, result);
end; end;
function parseType(var p: TParser): PNode;
begin
result := newNodeP(nkTypeSection, p);
while true do begin
case p.tok.tokType of
tkComment: skipComment(p, result);
tkType: begin
// type alias:
end;
tkEnum:
tkObject:
tkTuple:
else break;
end
end
end;
function complexOrSimpleStmt(var p: TParser): PNode; function complexOrSimpleStmt(var p: TParser): PNode;
begin begin
case p.tok.tokType of case p.tok.tokType of
@ -1410,8 +1400,9 @@ begin
tkMacro: result := parseRoutine(p, nkMacroDef); tkMacro: result := parseRoutine(p, nkMacroDef);
tkTemplate: result := parseRoutine(p, nkTemplateDef); tkTemplate: result := parseRoutine(p, nkTemplateDef);
tkConverter: result := parseRoutine(p, nkConverterDef); tkConverter: result := parseRoutine(p, nkConverterDef);
tkType: result := parseSection(p, nkTypeSection, parseTypeDef); tkType, tkEnum, tkObject, tkTuple:
tkConst: result := parseSection(p, nkConstSection, parseConstant); result := parseTypeAlias(p, nkTypeSection, parseTypeDef);
tkConst: result := parseConstSection(p);
tkWhen: result := parseIfOrWhen(p, nkWhenStmt); tkWhen: result := parseIfOrWhen(p, nkWhenStmt);
tkVar: result := parseSection(p, nkVarSection, parseVariable); tkVar: result := parseSection(p, nkVarSection, parseVariable);
else result := simpleStmt(p); else result := simpleStmt(p);
@ -1422,15 +1413,13 @@ function parseStmt(var p: TParser): PNode;
var var
a: PNode; a: PNode;
begin begin
if p.tok.tokType = tkInd then begin if p.tok.tokType = tkCurlyLe then begin
result := newNodeP(nkStmtList, p); result := newNodeP(nkStmtList, p);
pushInd(p.lex^, p.tok.indent);
getTok(p); getTok(p);
while true do begin while true do begin
case p.tok.tokType of case p.tok.tokType of
tkSad: getTok(p); tkSad, tkInd, tkDed: getTok(p);
tkEof: break; tkEof, tkCurlyRi: break;
tkDed: begin getTok(p); break end;
else begin else begin
a := complexOrSimpleStmt(p); a := complexOrSimpleStmt(p);
if a = nil then break; if a = nil then break;
@ -1438,7 +1427,7 @@ begin
end end
end end
end; end;
popInd(p.lex^); eat(p, tkCurlyRi);
end end
else begin else begin
// the case statement is only needed for better error messages: // the case statement is only needed for better error messages:
@ -1451,7 +1440,7 @@ begin
else begin else begin
result := simpleStmt(p); result := simpleStmt(p);
if result = nil then parMessage(p, errExprExpected, tokToStr(p.tok)); if result = nil then parMessage(p, errExprExpected, tokToStr(p.tok));
if p.tok.tokType = tkSad then getTok(p); if p.tok.tokType in [tkInd, tkDed, tkSad] then getTok(p);
end end
end end
end end
@ -1464,8 +1453,7 @@ begin
result := newNodeP(nkStmtList, p); result := newNodeP(nkStmtList, p);
while true do begin while true do begin
case p.tok.tokType of case p.tok.tokType of
tkSad: getTok(p); tkDed, tkInd, tkSad: getTok(p);
tkDed, tkInd: parMessage(p, errInvalidIndentation);
tkEof: break; tkEof: break;
else begin else begin
a := complexOrSimpleStmt(p); a := complexOrSimpleStmt(p);
@ -1481,11 +1469,7 @@ begin
result := nil; result := nil;
while true do begin while true do begin
case p.tok.tokType of case p.tok.tokType of
tkSad: getTok(p); tkDed, tkInd, tkSad: getTok(p);
tkDed, tkInd: begin
parMessage(p, errInvalidIndentation);
break;
end;
tkEof: break; tkEof: break;
else begin else begin
result := complexOrSimpleStmt(p); result := complexOrSimpleStmt(p);

36
nim/pendx.pas Executable file
View file

@ -0,0 +1,36 @@
//
//
// The Nimrod Compiler
// (c) Copyright 2009 Andreas Rumpf
//
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
unit pendx;
{$include config.inc}
interface
uses
nsystem, llstream, scanner, idents, strutils, ast, msgs, pnimsyn;
function ParseAll(var p: TParser): PNode;
function parseTopLevelStmt(var p: TParser): PNode;
// implements an iterator. Returns the next top-level statement or nil if end
// of stream.
implementation
function ParseAll(var p: TParser): PNode;
begin
result := nil
end;
function parseTopLevelStmt(var p: TParser): PNode;
begin
result := nil
end;
end.

View file

@ -72,6 +72,7 @@ procedure optSad(var p: TParser);
procedure optInd(var p: TParser; n: PNode); procedure optInd(var p: TParser; n: PNode);
procedure indAndComment(var p: TParser; n: PNode); procedure indAndComment(var p: TParser; n: PNode);
procedure setBaseFlags(n: PNode; base: TNumericalBase);
function parseSymbol(var p: TParser): PNode; function parseSymbol(var p: TParser): PNode;
function accExpr(var p: TParser): PNode; function accExpr(var p: TParser): PNode;
@ -1069,12 +1070,12 @@ begin
end end
end; end;
function parseImportStmt(var p: TParser): PNode; function parseImportOrIncludeStmt(var p: TParser; kind: TNodeKind): PNode;
var var
a: PNode; a: PNode;
begin begin
result := newNodeP(nkImportStmt, p); result := newNodeP(kind, p);
getTok(p); // skip `import` getTok(p); // skip `import` or `include`
optInd(p, result); optInd(p, result);
while true do begin while true do begin
case p.tok.tokType of case p.tok.tokType of
@ -1104,42 +1105,6 @@ begin
end; end;
end; end;
function parseIncludeStmt(var p: TParser): PNode;
var
a: PNode;
begin
result := newNodeP(nkIncludeStmt, p);
getTok(p); // skip `include`
optInd(p, result);
while true do begin
case p.tok.tokType of
tkEof, tkSad, tkDed: break;
tkSymbol, tkAccent: a := parseSymbol(p);
tkRStrLit: begin
a := newStrNodeP(nkRStrLit, p.tok.literal, p);
getTok(p)
end;
tkStrLit: begin
a := newStrNodeP(nkStrLit, p.tok.literal, p);
getTok(p);
end;
tkTripleStrLit: begin
a := newStrNodeP(nkTripleStrLit, p.tok.literal, p);
getTok(p)
end;
else begin
parMessage(p, errIdentifierExpected, tokToStr(p.tok));
break
end;
end;
addSon(result, a);
//optInd(p, a);
if p.tok.tokType <> tkComma then break;
getTok(p);
optInd(p, a)
end;
end;
function parseFromStmt(var p: TParser): PNode; function parseFromStmt(var p: TParser): PNode;
var var
a: PNode; a: PNode;
@ -1717,9 +1682,9 @@ begin
tkBreak: result := parseBreakOrContinue(p, nkBreakStmt); tkBreak: result := parseBreakOrContinue(p, nkBreakStmt);
tkContinue: result := parseBreakOrContinue(p, nkContinueStmt); tkContinue: result := parseBreakOrContinue(p, nkContinueStmt);
tkCurlyDotLe: result := parsePragma(p); tkCurlyDotLe: result := parsePragma(p);
tkImport: result := parseImportStmt(p); tkImport: result := parseImportOrIncludeStmt(p, nkImportStmt);
tkFrom: result := parseFromStmt(p); tkFrom: result := parseFromStmt(p);
tkInclude: result := parseIncludeStmt(p); tkInclude: result := parseImportOrIncludeStmt(p, nkIncludeStmt);
tkComment: result := newCommentStmt(p); tkComment: result := newCommentStmt(p);
else begin else begin
if isExprStart(p) then if isExprStart(p) then

287
nim/semgnrc.pas Executable file
View file

@ -0,0 +1,287 @@
//
//
// The Nimrod Compiler
// (c) Copyright 2009 Andreas Rumpf
//
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
// This implements the first pass over the generic body; it resolves some
// symbols. Thus for generics there is a two-phase symbol lookup just like
// in C++.
// A problem is that it cannot be detected if the symbol is introduced
// as in ``var x = ...`` or used because macros/templates can hide this!
// So we have to eval templates/macros right here so that symbol
// lookup can be accurate.
type
TSemGenericFlag = (withinBind, withinTypeDesc);
TSemGenericFlags = set of TSemGenericFlag;
function semGenericStmt(c: PContext; n: PNode;
flags: TSemGenericFlags = {@set}[]): PNode; forward;
function semGenericStmtScope(c: PContext; n: PNode;
flags: TSemGenericFlags = {@set}[]): PNode;
begin
openScope(c.tab);
result := semGenericStmt(c, n, flags);
closeScope(c.tab);
end;
function semGenericStmtSymbol(c: PContext; n: PNode; s: PSym): PNode;
begin
case s.kind of
skUnknown: begin
// Introduced in this pass! Leave it as an identifier.
result := n;
end;
skProc, skMethod, skIterator, skConverter: result := symChoice(c, n, s);
skTemplate: result := semTemplateExpr(c, n, s, false);
skMacro: result := semMacroExpr(c, n, s, false);
skGenericParam: result := newSymNode(s);
skParam: result := n;
skType: begin
if (s.typ <> nil) and (s.typ.kind <> tyGenericParam) then
result := newSymNode(s)
else
result := n
end
else result := newSymNode(s)
end
end;
function getIdentNode(n: PNode): PNode;
begin
case n.kind of
nkPostfix: result := getIdentNode(n.sons[1]);
nkPragmaExpr, nkAccQuoted: result := getIdentNode(n.sons[0]);
nkIdent: result := n;
else begin
illFormedAst(n);
result := nil
end
end
end;
function semGenericStmt(c: PContext; n: PNode;
flags: TSemGenericFlags = {@set}[]): PNode;
var
i, j, L: int;
a: PNode;
s: PSym;
begin
result := n;
if n = nil then exit;
case n.kind of
nkIdent, nkAccQuoted: begin
s := lookUp(c, n);
if withinBind in flags then
result := symChoice(c, n, s)
else
result := semGenericStmtSymbol(c, n, s);
end;
nkDotExpr: begin
s := QualifiedLookUp(c, n, true);
if s <> nil then
result := semGenericStmtSymbol(c, n, s);
end;
nkSym..nkNilLit: begin end;
nkBind: result := semGenericStmt(c, n.sons[0], {@set}[withinBind]);
nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit: begin
// check if it is an expression macro:
checkMinSonsLen(n, 1);
s := qualifiedLookup(c, n.sons[0], false);
if (s <> nil) then begin
case s.kind of
skMacro: begin result := semMacroExpr(c, n, s, false); exit end;
skTemplate: begin result := semTemplateExpr(c, n, s, false); exit end;
skUnknown, skParam: begin
// Leave it as an identifier.
end;
skProc, skMethod, skIterator, skConverter: begin
n.sons[0] := symChoice(c, n.sons[0], s);
end;
skGenericParam: n.sons[0] := newSymNode(s);
skType: begin
// bad hack for generics:
if (s.typ <> nil) and (s.typ.kind <> tyGenericParam) then begin
n.sons[0] := newSymNode(s);
end
end;
else n.sons[0] := newSymNode(s)
end
end;
for i := 1 to sonsLen(n)-1 do
n.sons[i] := semGenericStmt(c, n.sons[i], flags);
end;
nkMacroStmt: begin
result := semMacroStmt(c, n, false);
end;
nkIfStmt: begin
for i := 0 to sonsLen(n)-1 do
n.sons[i] := semGenericStmtScope(c, n.sons[i]);
end;
nkWhileStmt: begin
openScope(c.tab);
for i := 0 to sonsLen(n)-1 do
n.sons[i] := semGenericStmt(c, n.sons[i]);
closeScope(c.tab);
end;
nkCaseStmt: begin
openScope(c.tab);
n.sons[0] := semGenericStmt(c, n.sons[0]);
for i := 1 to sonsLen(n)-1 do begin
a := n.sons[i];
checkMinSonsLen(a, 1);
L := sonsLen(a);
for j := 0 to L-2 do
a.sons[j] := semGenericStmt(c, a.sons[j]);
a.sons[L-1] := semGenericStmtScope(c, a.sons[L-1]);
end;
closeScope(c.tab);
end;
nkForStmt: begin
L := sonsLen(n);
openScope(c.tab);
n.sons[L-2] := semGenericStmt(c, n.sons[L-2]);
for i := 0 to L-3 do
addDecl(c, newSymS(skUnknown, n.sons[i], c));
n.sons[L-1] := semGenericStmt(c, n.sons[L-1]);
closeScope(c.tab);
end;
nkBlockStmt, nkBlockExpr, nkBlockType: begin
checkSonsLen(n, 2);
openScope(c.tab);
if n.sons[0] <> nil then
addDecl(c, newSymS(skUnknown, n.sons[0], c));
n.sons[1] := semGenericStmt(c, n.sons[1]);
closeScope(c.tab);
end;
nkTryStmt: begin
checkMinSonsLen(n, 2);
n.sons[0] := semGenericStmtScope(c, n.sons[0]);
for i := 1 to sonsLen(n)-1 do begin
a := n.sons[i];
checkMinSonsLen(a, 1);
L := sonsLen(a);
for j := 0 to L-2 do
a.sons[j] := semGenericStmt(c, a.sons[j], {@set}[withinTypeDesc]);
a.sons[L-1] := semGenericStmtScope(c, a.sons[L-1]);
end;
end;
nkVarSection: begin
for i := 0 to sonsLen(n)-1 do begin
a := n.sons[i];
if a.kind = nkCommentStmt then continue;
if (a.kind <> nkIdentDefs) and (a.kind <> nkVarTuple) then
IllFormedAst(a);
checkMinSonsLen(a, 3);
L := sonsLen(a);
a.sons[L-2] := semGenericStmt(c, a.sons[L-2], {@set}[withinTypeDesc]);
a.sons[L-1] := semGenericStmt(c, a.sons[L-1]);
for j := 0 to L-3 do
addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c));
end
end;
nkGenericParams: begin
for i := 0 to sonsLen(n)-1 do begin
a := n.sons[i];
if (a.kind <> nkIdentDefs) then IllFormedAst(a);
checkMinSonsLen(a, 3);
L := sonsLen(a);
a.sons[L-2] := semGenericStmt(c, a.sons[L-2], {@set}[withinTypeDesc]);
// do not perform symbol lookup for default expressions
for j := 0 to L-3 do
addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c));
end
end;
nkConstSection: begin
for i := 0 to sonsLen(n)-1 do begin
a := n.sons[i];
if a.kind = nkCommentStmt then continue;
if (a.kind <> nkConstDef) then IllFormedAst(a);
checkSonsLen(a, 3);
addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c));
a.sons[1] := semGenericStmt(c, a.sons[1], {@set}[withinTypeDesc]);
a.sons[2] := semGenericStmt(c, a.sons[2]);
end
end;
nkTypeSection: begin
for i := 0 to sonsLen(n)-1 do begin
a := n.sons[i];
if a.kind = nkCommentStmt then continue;
if (a.kind <> nkTypeDef) then IllFormedAst(a);
checkSonsLen(a, 3);
addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c));
end;
for i := 0 to sonsLen(n)-1 do begin
a := n.sons[i];
if a.kind = nkCommentStmt then continue;
if (a.kind <> nkTypeDef) then IllFormedAst(a);
checkSonsLen(a, 3);
if a.sons[1] <> nil then begin
openScope(c.tab);
a.sons[1] := semGenericStmt(c, a.sons[1]);
a.sons[2] := semGenericStmt(c, a.sons[2], {@set}[withinTypeDesc]);
closeScope(c.tab);
end
else
a.sons[2] := semGenericStmt(c, a.sons[2], {@set}[withinTypeDesc]);
end
end;
nkEnumTy: begin
checkMinSonsLen(n, 1);
if n.sons[0] <> nil then
n.sons[0] := semGenericStmt(c, n.sons[0], {@set}[withinTypeDesc]);
for i := 1 to sonsLen(n)-1 do begin
case n.sons[i].kind of
nkEnumFieldDef: a := n.sons[i].sons[0];
nkIdent: a := n.sons[i];
else illFormedAst(n);
end;
addDeclAt(c, newSymS(skUnknown, getIdentNode(a.sons[i]), c),
c.tab.tos-1);
end
end;
nkObjectTy, nkTupleTy: begin end;
nkFormalParams: begin
checkMinSonsLen(n, 1);
if n.sons[0] <> nil then
n.sons[0] := semGenericStmt(c, n.sons[0], {@set}[withinTypeDesc]);
for i := 1 to sonsLen(n)-1 do begin
a := n.sons[i];
if (a.kind <> nkIdentDefs) then IllFormedAst(a);
checkMinSonsLen(a, 3);
L := sonsLen(a);
a.sons[L-1] := semGenericStmt(c, a.sons[L-2], {@set}[withinTypeDesc]);
a.sons[L-1] := semGenericStmt(c, a.sons[L-1]);
for j := 0 to L-3 do begin
addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c));
end
end
end;
nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
nkIteratorDef, nkLambda: begin
checkSonsLen(n, codePos+1);
addDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c));
openScope(c.tab);
n.sons[genericParamsPos] := semGenericStmt(c, n.sons[genericParamsPos]);
if n.sons[paramsPos] <> nil then begin
if n.sons[paramsPos].sons[0] <> nil then
addDecl(c, newSym(skUnknown, getIdent('result'), nil));
n.sons[paramsPos] := semGenericStmt(c, n.sons[paramsPos]);
end;
n.sons[pragmasPos] := semGenericStmt(c, n.sons[pragmasPos]);
n.sons[codePos] := semGenericStmtScope(c, n.sons[codePos]);
closeScope(c.tab);
end
else begin
for i := 0 to sonsLen(n)-1 do
result.sons[i] := semGenericStmt(c, n.sons[i], flags);
end
end
end;

View file

@ -147,7 +147,8 @@ begin
end end
end; end;
function resolveTemplateParams(c: PContext; n: PNode; withinBind: bool): PNode; function resolveTemplateParams(c: PContext; n: PNode; withinBind: bool;
var toBind: TIntSet): PNode;
var var
i: int; i: int;
s: PSym; s: PSym;
@ -155,7 +156,7 @@ begin
if n = nil then begin result := nil; exit end; if n = nil then begin result := nil; exit end;
case n.kind of case n.kind of
nkIdent: begin nkIdent: begin
if not withinBind then begin if not withinBind and not IntSetContains(toBind, n.ident.id) then begin
s := SymTabLocalGet(c.Tab, n.ident); s := SymTabLocalGet(c.Tab, n.ident);
if (s <> nil) then begin if (s <> nil) then begin
result := newSymNode(s); result := newSymNode(s);
@ -165,17 +166,18 @@ begin
result := n result := n
end end
else begin else begin
IntSetIncl(toBind, n.ident.id);
result := symChoice(c, n, lookup(c, n)) result := symChoice(c, n, lookup(c, n))
end end
end; end;
nkSym..nkNilLit: // atom nkSym..nkNilLit: // atom
result := n; result := n;
nkBind: nkBind:
result := resolveTemplateParams(c, n.sons[0], true); result := resolveTemplateParams(c, n.sons[0], true, toBind);
else begin else begin
result := n; result := n;
for i := 0 to sonsLen(n)-1 do for i := 0 to sonsLen(n)-1 do
result.sons[i] := resolveTemplateParams(c, n.sons[i], withinBind); result.sons[i] := resolveTemplateParams(c, n.sons[i], withinBind, toBind);
end end
end end
end; end;
@ -211,6 +213,7 @@ end;
function semTemplateDef(c: PContext; n: PNode): PNode; function semTemplateDef(c: PContext; n: PNode): PNode;
var var
s: PSym; s: PSym;
toBind: TIntSet;
begin begin
if c.p.owner.kind = skModule then begin if c.p.owner.kind = skModule then begin
s := semIdentVis(c, skTemplate, n.sons[0], {@set}[sfStar]); s := semIdentVis(c, skTemplate, n.sons[0], {@set}[sfStar]);
@ -248,7 +251,8 @@ begin
addParams(c, s.typ.n); addParams(c, s.typ.n);
// resolve parameters: // resolve parameters:
n.sons[codePos] := resolveTemplateParams(c, n.sons[codePos], false); IntSetInit(toBind);
n.sons[codePos] := resolveTemplateParams(c, n.sons[codePos], false, toBind);
if not (s.typ.sons[0].kind in [tyStmt, tyTypeDesc]) then if not (s.typ.sons[0].kind in [tyStmt, tyTypeDesc]) then
n.sons[codePos] := transformToExpr(n.sons[codePos]); n.sons[codePos] := transformToExpr(n.sons[codePos]);

View file

@ -15,7 +15,7 @@ interface
uses uses
nsystem, strutils, llstream, ast, astalgo, idents, scanner, options, msgs, nsystem, strutils, llstream, ast, astalgo, idents, scanner, options, msgs,
pnimsyn, ptmplsyn, filters, rnimsyn; pnimsyn, pbraces, ptmplsyn, filters, rnimsyn;
type type
TFilterKind = (filtNone, filtTemplate, filtReplace, filtStrip); TFilterKind = (filtNone, filtTemplate, filtReplace, filtStrip);
@ -68,8 +68,8 @@ function parseAll(var p: TParsers): PNode;
begin begin
case p.skin of case p.skin of
skinStandard: result := pnimsyn.parseAll(p.parser); skinStandard: result := pnimsyn.parseAll(p.parser);
skinBraces, skinEndX: InternalError('parser to implement'); skinBraces: result := pbraces.parseAll(p.parser);
// skinBraces: result := pbraces.parseAll(p.parser); skinEndX: InternalError('parser to implement');
// skinEndX: result := pendx.parseAll(p.parser); // skinEndX: result := pendx.parseAll(p.parser);
end end
end; end;
@ -78,8 +78,8 @@ function parseTopLevelStmt(var p: TParsers): PNode;
begin begin
case p.skin of case p.skin of
skinStandard: result := pnimsyn.parseTopLevelStmt(p.parser); skinStandard: result := pnimsyn.parseTopLevelStmt(p.parser);
skinBraces, skinEndX: InternalError('parser to implement'); skinBraces: result := pbraces.parseTopLevelStmt(p.parser);
//skinBraces: result := pbraces.parseTopLevelStmt(p.parser); skinEndX: InternalError('parser to implement');
//skinEndX: result := pendx.parseTopLevelStmt(p.parser); //skinEndX: result := pendx.parseTopLevelStmt(p.parser);
end end
end; end;

35
nim/vis.pas Executable file
View file

@ -0,0 +1,35 @@
//
//
// The Nimrod Compiler
// (c) Copyright 2009 Andreas Rumpf
//
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
unit vis;
// Virtual instruction set for Nimrod. This is used for LLVM code generation.
interface
{$include 'config.inc'}
uses
nsystem, ast, astalgo, strutils, nhashes, trees, platform, magicsys,
extccomp, options, nversion, nimsets, msgs, crc, bitsets, idents,
lists, types, ccgutils, nos, ntime, ropes, nmath, passes, rodread,
wordrecg, rnimsyn, treetab;
type
TInstrKind = (
insAddi,
);
TInstruction = record
end;
implementation
end.

View file

@ -178,7 +178,7 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) =
Exec("pdflatex " & changeFileExt(d, "tex")) Exec("pdflatex " & changeFileExt(d, "tex"))
Exec("pdflatex " & changeFileExt(d, "tex")) Exec("pdflatex " & changeFileExt(d, "tex"))
# delete all the crappy temporary files: # delete all the crappy temporary files:
var pdf = extractFileTrunk(d) & ".pdf" var pdf = splitFile(d).name & ".pdf"
moveFile(destPath / pdf, pdf) moveFile(destPath / pdf, pdf)
removeFile(changeFileExt(pdf, "aux")) removeFile(changeFileExt(pdf, "aux"))
if existsFile(changeFileExt(pdf, "toc")): if existsFile(changeFileExt(pdf, "toc")):

View file

@ -17,6 +17,14 @@ feature that Nimrod inherited from Lisp is that Nimrod's abstract syntax tree
can be used to create domain specific languages. Nimrod does not sacrifice can be used to create domain specific languages. Nimrod does not sacrifice
flexibility for speed. You get both. flexibility for speed. You get both.
..
Don't give me that marketing crap. What is Nimrod?
--------------------------------------------------
Nimrod = Mutable value based datatypes + static binding + sugar to make
this programming modell as convenient as possible
How is Nimrod licensed? How is Nimrod licensed?
----------------------- -----------------------