diff options
-rwxr-xr-x | doc/astspec.txt | 12 | ||||
-rwxr-xr-x | doc/filters.txt | 4 | ||||
-rwxr-xr-x | doc/manual.txt | 46 | ||||
-rwxr-xr-x | doc/nimrodc.txt | 26 | ||||
-rwxr-xr-x | doc/pegdocs.txt | 21 | ||||
-rwxr-xr-x | doc/theindex.txt | 231 | ||||
-rwxr-xr-x | lib/pure/pegs.nim | 287 | ||||
-rwxr-xr-x | lib/pure/unicode.nim | 6 | ||||
-rwxr-xr-x | nim/llvmdata.pas | 139 | ||||
-rwxr-xr-x | nim/pbraces.pas | 122 | ||||
-rwxr-xr-x | nim/pendx.pas | 36 | ||||
-rwxr-xr-x | nim/pnimsyn.pas | 47 | ||||
-rwxr-xr-x | nim/semgnrc.pas | 287 | ||||
-rwxr-xr-x | nim/semtempl.pas | 14 | ||||
-rwxr-xr-x | nim/syntaxes.pas | 10 | ||||
-rwxr-xr-x | nim/vis.pas | 35 | ||||
-rwxr-xr-x | tools/nimweb.nim | 2 | ||||
-rwxr-xr-x | web/question.txt | 8 |
18 files changed, 953 insertions, 380 deletions
diff --git a/doc/astspec.txt b/doc/astspec.txt index eec2808fd..01c1adba3 100755 --- a/doc/astspec.txt +++ b/doc/astspec.txt @@ -20,7 +20,7 @@ contains: PNimrodNode = ref TNimrodNode TNimrodNode {.final.} = object - case kind ## the node's kind + case kind: TNimrodNodeKind ## the node's kind of nnkNone, nnkEmpty, nnkNilLit: nil ## node contains no additional fields 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(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 ================ @@ -72,8 +77,9 @@ Nimrod expression corresponding AST Identifiers are ``nnkIdent`` nodes. After the name lookup pass these nodes 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 -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 ================= diff --git a/doc/filters.txt b/doc/filters.txt index ffeb6808a..0cbb3319d 100755 --- a/doc/filters.txt +++ b/doc/filters.txt @@ -4,8 +4,8 @@ Parsers and Filters .. contents:: -The Nimrod compiler contains multiple parsers. (The standard is -indentation-based.) Two others are available: The `braces`:idx: parser and the +The Nimrod compiler contains multiple parsers. The standard is +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. To use a different parser for a source file the *shebang* notation is used: diff --git a/doc/manual.txt b/doc/manual.txt index 978ef1496..929b01181 100755 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -951,7 +951,7 @@ of the following conditions hold: 3) The procedure has a calling convention that differs from ``nimcall``. 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. @@ -1800,7 +1800,7 @@ return values. This can be done in a cleaner way by returning a tuple: assert t.res == 1 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 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 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 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`` 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 powerful programming construct that still suffices. So the "check list" is: @@ -2356,7 +2394,7 @@ verify this. 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. diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt index 3200b135b..88ca52939 100755 --- a/doc/nimrodc.txt +++ b/doc/nimrodc.txt @@ -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* 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 ~~~~~~~~~~~~~~ @@ -231,7 +246,7 @@ compiler to activate (or deactivate) dead code elimination for the module the pragma appers in. 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 - no matter if it is globally active or not. @@ -244,7 +259,7 @@ Example: Disabling certain messages -------------------------- 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 identifier that can be used to enable or disable it: @@ -300,9 +315,10 @@ However it is not efficient to do: .. code-block:: Nimrod 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 -efficient than any hand-coded scheme. +.. + 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 + efficient than any hand-coded scheme. .. diff --git a/doc/pegdocs.txt b/doc/pegdocs.txt index 943acc545..e2c228cf3 100755 --- a/doc/pegdocs.txt +++ b/doc/pegdocs.txt @@ -60,6 +60,8 @@ notation meaning ``_`` Any Unicode character: If there is an UTF-8 character ahead, consume it and indicate success. Otherwise indicate 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`. **Left recursive rules are not possible and crash the matching engine.** @@ -118,14 +120,15 @@ The PEG parser implements this grammar (written in PEG syntax):: "'" ("\\" . / [^'])* "'") builtin <- "\\" identifier / [^\13\10] - comment <- '#' !\n* \n + comment <- '#' @ \n ig <- (\s / comment)* # things to ignore rule <- identifier \s* "<-" expr ig identNoArrow <- identifier !(\s* "<-") - primary <- (ig '&' / ig '!')* ((ig identNoArrow / ig charset / ig stringlit - / ig builtin / ig '.' / ig '_' - / (ig "(" expr ig ")")) + primary <- (ig '&' / ig '!' / ig '@')* + ((ig identNoArrow / ig charset / ig stringlit + / ig builtin / ig '.' / ig '_' + / (ig "(" expr ig ")")) (ig '?' / ig '*' / ig '+')*) # Concatenation has higher priority than choice: @@ -153,16 +156,16 @@ Determine the ``#include``'ed files of a C file: .. code-block:: nimrod for line in lines("myfile.c"): if line =~ peg"""s <- ws '#include' ws '"' {[^"]+} '"' ws - comment <- '/*' (!'*/' . )* '*/' / '//' .* - ws <- (comment / \s+)* """: + comment <- '/*' @ '*/' / '//' .* + ws <- (comment / \s+)* """: echo matches[0] PEG vs regular expression ------------------------- -As a regular expression ``\[.*\]`` maches longest possible text between ``'['`` -and ``']'``. As a PEG it never matches anything, because a PEG is +As a regular expression ``\[.*\]`` matches the longest possible text between +``'['`` and ``']'``. As a PEG it never matches anything, because a PEG is 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: ``*`` should not be greedy, so ``\[.*?\]`` should be used. diff --git a/doc/theindex.txt b/doc/theindex.txt index 922dab769..e9eb5080f 100755 --- a/doc/theindex.txt +++ b/doc/theindex.txt @@ -7,7 +7,7 @@ Index `!`:idx: - * `pegs.html#114 <pegs.html#114>`_ + * `pegs.html#115 <pegs.html#115>`_ * `macros.html#114 <macros.html#114>`_ `!=`:idx: @@ -24,7 +24,7 @@ Index * `system.html#426 <system.html#426>`_ * `times.html#109 <times.html#109>`_ * `times.html#110 <times.html#110>`_ - * `pegs.html#148 <pegs.html#148>`_ + * `pegs.html#133 <pegs.html#133>`_ * `macros.html#115 <macros.html#115>`_ `%`:idx: @@ -47,7 +47,7 @@ Index * `system.html#462 <system.html#462>`_ * `system.html#463 <system.html#463>`_ * `system.html#464 <system.html#464>`_ - * `pegs.html#113 <pegs.html#113>`_ + * `pegs.html#114 <pegs.html#114>`_ `*`:idx: * `system.html#212 <system.html#212>`_ @@ -82,7 +82,7 @@ Index * `system.html#309 <system.html#309>`_ * `system.html#320 <system.html#320>`_ * `complex.html#103 <complex.html#103>`_ - * `pegs.html#112 <pegs.html#112>`_ + * `pegs.html#113 <pegs.html#113>`_ `+%`:idx: * `system.html#272 <system.html#272>`_ @@ -153,15 +153,15 @@ Index * `times.html#114 <times.html#114>`_ `<%`:idx: - `unicode.html#104 <unicode.html#104>`_ - - `<%`:idx: * `system.html#302 <system.html#302>`_ * `system.html#303 <system.html#303>`_ * `system.html#304 <system.html#304>`_ * `system.html#305 <system.html#305>`_ * `system.html#306 <system.html#306>`_ + `<%`:idx: + `unicode.html#104 <unicode.html#104>`_ + `<=`:idx: * `system.html#257 <system.html#257>`_ * `system.html#258 <system.html#258>`_ @@ -181,15 +181,15 @@ Index `times.html#115 <times.html#115>`_ `<=%`:idx: + `unicode.html#103 <unicode.html#103>`_ + + `<=%`:idx: * `system.html#297 <system.html#297>`_ * `system.html#298 <system.html#298>`_ * `system.html#299 <system.html#299>`_ * `system.html#300 <system.html#300>`_ * `system.html#301 <system.html#301>`_ - `<=%`:idx: - `unicode.html#103 <unicode.html#103>`_ - `==`:idx: * `md5.html#107 <md5.html#107>`_ * `system.html#252 <system.html#252>`_ @@ -211,12 +211,13 @@ Index * `complex.html#102 <complex.html#102>`_ * `unicode.html#105 <unicode.html#105>`_ * `macros.html#116 <macros.html#116>`_ + * `macros.html#117 <macros.html#117>`_ `=~`:idx: - `pegs.html#138 <pegs.html#138>`_ + `regexprs.html#111 <regexprs.html#111>`_ `=~`:idx: - `regexprs.html#108 <regexprs.html#108>`_ + `pegs.html#140 <pegs.html#140>`_ `>`:idx: `system.html#349 <system.html#349>`_ @@ -234,13 +235,14 @@ Index `pegs.html#110 <pegs.html#110>`_ `@`: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>`_ + `macros.html#112 <macros.html#112>`_ `[]`:idx: - `macros.html#112 <macros.html#112>`_ + `strtabs.html#107 <strtabs.html#107>`_ `[]=`:idx: `macros.html#113 <macros.html#113>`_ @@ -279,8 +281,8 @@ Index * `system.html#368 <system.html#368>`_ * `system.html#369 <system.html#369>`_ * `parsesql.html#108 <parsesql.html#108>`_ - * `macros.html#118 <macros.html#118>`_ * `macros.html#119 <macros.html#119>`_ + * `macros.html#120 <macros.html#120>`_ `addf`:idx: `strutils.html#111 <strutils.html#111>`_ @@ -332,16 +334,16 @@ Index * `system.html#241 <system.html#241>`_ `any`:idx: - `pegs.html#116 <pegs.html#116>`_ + `pegs.html#117 <pegs.html#117>`_ `any character`:idx: - `pegs.html#115 <pegs.html#115>`_ + `pegs.html#116 <pegs.html#116>`_ `any rune`:idx: - `pegs.html#117 <pegs.html#117>`_ + `pegs.html#118 <pegs.html#118>`_ `anyRune`:idx: - `pegs.html#118 <pegs.html#118>`_ + `pegs.html#119 <pegs.html#119>`_ `apostrophe`:idx: `manual.html#129 <manual.html#129>`_ @@ -403,7 +405,8 @@ Index `xmlgen.html#111 <xmlgen.html#111>`_ `backslash`:idx: - `manual.html#127 <manual.html#127>`_ + * `manual.html#127 <manual.html#127>`_ + * `regexprs.html#101 <regexprs.html#101>`_ `backspace`:idx: `manual.html#132 <manual.html#132>`_ @@ -476,7 +479,7 @@ Index `xmlgen.html#118 <xmlgen.html#118>`_ `capture`:idx: - `pegs.html#121 <pegs.html#121>`_ + `pegs.html#122 <pegs.html#122>`_ `card`:idx: `system.html#175 <system.html#175>`_ @@ -695,12 +698,12 @@ Index `CompileDate`:idx: `system.html#390 <system.html#390>`_ - `CompileTime`:idx: - `system.html#391 <system.html#391>`_ - `compileTime`:idx: `manual.html#229 <manual.html#229>`_ + `CompileTime`:idx: + `system.html#391 <system.html#391>`_ + `complex statements`:idx: `manual.html#178 <manual.html#178>`_ @@ -719,8 +722,8 @@ Index * `strutils.html#137 <strutils.html#137>`_ * `strutils.html#138 <strutils.html#138>`_ * `strutils.html#139 <strutils.html#139>`_ - * `pegs.html#139 <pegs.html#139>`_ - * `pegs.html#140 <pegs.html#140>`_ + * `pegs.html#141 <pegs.html#141>`_ + * `pegs.html#142 <pegs.html#142>`_ `continue`:idx: `manual.html#198 <manual.html#198>`_ @@ -736,10 +739,10 @@ Index `system.html#407 <system.html#407>`_ `copyNimNode`:idx: - `macros.html#135 <macros.html#135>`_ + `macros.html#136 <macros.html#136>`_ `copyNimTree`:idx: - `macros.html#136 <macros.html#136>`_ + `macros.html#137 <macros.html#137>`_ `coreAttr`:idx: `xmlgen.html#103 <xmlgen.html#103>`_ @@ -1185,7 +1188,7 @@ Index `del`:idx: * `xmlgen.html#124 <xmlgen.html#124>`_ - * `macros.html#120 <macros.html#120>`_ + * `macros.html#121 <macros.html#121>`_ `delete`:idx: `strutils.html#156 <strutils.html#156>`_ @@ -1198,7 +1201,7 @@ Index `xmlgen.html#125 <xmlgen.html#125>`_ `digits`:idx: - `pegs.html#125 <pegs.html#125>`_ + `pegs.html#126 <pegs.html#126>`_ `Digits`:idx: `strutils.html#104 <strutils.html#104>`_ @@ -1290,10 +1293,10 @@ Index `system.html#160 <system.html#160>`_ `EInvalidPeg`:idx: - `pegs.html#149 <pegs.html#149>`_ + `pegs.html#150 <pegs.html#150>`_ `EInvalidRegEx`:idx: - `regexprs.html#101 <regexprs.html#101>`_ + `regexprs.html#104 <regexprs.html#104>`_ `EInvalidSql`:idx: `parsesql.html#103 <parsesql.html#103>`_ @@ -1322,7 +1325,7 @@ Index `endsWith`:idx: * `strutils.html#148 <strutils.html#148>`_ - * `pegs.html#142 <pegs.html#142>`_ + * `pegs.html#144 <pegs.html#144>`_ `ENoExceptionToReraise`:idx: * `manual.html#187 <manual.html#187>`_ @@ -1334,12 +1337,12 @@ Index `enum_cursor_type`:idx: `mysql.html#237 <mysql.html#237>`_ - `Enumeration`:idx: - `manual.html#149 <manual.html#149>`_ - `enumeration`:idx: `tut1.html#113 <tut1.html#113>`_ + `Enumeration`:idx: + `manual.html#149 <manual.html#149>`_ + `enum_field_types`:idx: `mysql.html#202 <mysql.html#202>`_ @@ -1390,7 +1393,7 @@ Index `error`:idx: * `manual.html#226 <manual.html#226>`_ * `manual.html#230 <manual.html#230>`_ - * `macros.html#137 <macros.html#137>`_ + * `macros.html#138 <macros.html#138>`_ `errorMsg`:idx: `parsexml.html#120 <parsexml.html#120>`_ @@ -1478,13 +1481,13 @@ Index `os.html#132 <os.html#132>`_ `expectKind`:idx: - `macros.html#146 <macros.html#146>`_ + `macros.html#147 <macros.html#147>`_ `expectLen`:idx: - `macros.html#148 <macros.html#148>`_ + `macros.html#149 <macros.html#149>`_ `expectMinLen`:idx: - `macros.html#147 <macros.html#147>`_ + `macros.html#148 <macros.html#148>`_ `exportc`:idx: `nimrodc.html#102 <nimrodc.html#102>`_ @@ -1632,10 +1635,10 @@ Index * `strutils.html#119 <strutils.html#119>`_ * `strutils.html#120 <strutils.html#120>`_ * `strutils.html#121 <strutils.html#121>`_ - * `regexprs.html#106 <regexprs.html#106>`_ - * `regexprs.html#107 <regexprs.html#107>`_ - * `pegs.html#136 <pegs.html#136>`_ - * `pegs.html#137 <pegs.html#137>`_ + * `regexprs.html#109 <regexprs.html#109>`_ + * `regexprs.html#110 <regexprs.html#110>`_ + * `pegs.html#138 <pegs.html#138>`_ + * `pegs.html#139 <pegs.html#139>`_ `float`:idx: `system.html#106 <system.html#106>`_ @@ -1647,10 +1650,10 @@ Index `system.html#108 <system.html#108>`_ `floatVal`:idx: - `macros.html#123 <macros.html#123>`_ + `macros.html#124 <macros.html#124>`_ `floatVal=`:idx: - `macros.html#129 <macros.html#129>`_ + `macros.html#130 <macros.html#130>`_ `FlushFile`:idx: `system.html#503 <system.html#503>`_ @@ -1715,6 +1718,9 @@ Index `generalized raw string literal`:idx: `manual.html#136 <manual.html#136>`_ + `generic character types`:idx: + `regexprs.html#102 <regexprs.html#102>`_ + `Generics`:idx: * `manual.html#212 <manual.html#212>`_ * `tut2.html#109 <tut2.html#109>`_ @@ -1987,7 +1993,7 @@ Index `hint`:idx: * `manual.html#224 <manual.html#224>`_ * `manual.html#233 <manual.html#233>`_ - * `macros.html#139 <macros.html#139>`_ + * `macros.html#140 <macros.html#140>`_ `hostCPU`:idx: `system.html#398 <system.html#398>`_ @@ -2001,13 +2007,13 @@ Index `hr`:idx: `xmlgen.html#140 <xmlgen.html#140>`_ + `html`:idx: + `xmlgen.html#139 <xmlgen.html#139>`_ + `HTML`:idx: * `parsexml.html#102 <parsexml.html#102>`_ * `xmlgen.html#102 <xmlgen.html#102>`_ - `html`:idx: - `xmlgen.html#139 <xmlgen.html#139>`_ - `HTTPPOST_BUFFER`:idx: `libcurl.html#266 <libcurl.html#266>`_ @@ -2033,14 +2039,14 @@ Index `xmlgen.html#141 <xmlgen.html#141>`_ `ident`:idx: - * `pegs.html#129 <pegs.html#129>`_ - * `macros.html#125 <macros.html#125>`_ + * `pegs.html#130 <pegs.html#130>`_ + * `macros.html#126 <macros.html#126>`_ `ident=`:idx: - `macros.html#131 <macros.html#131>`_ + `macros.html#132 <macros.html#132>`_ `identChars`:idx: - `pegs.html#127 <pegs.html#127>`_ + `pegs.html#128 <pegs.html#128>`_ `IdentChars`:idx: `strutils.html#105 <strutils.html#105>`_ @@ -2052,7 +2058,7 @@ Index `manual.html#116 <manual.html#116>`_ `identStartChars`:idx: - `pegs.html#128 <pegs.html#128>`_ + `pegs.html#129 <pegs.html#129>`_ `IdentStartChars`:idx: `strutils.html#106 <strutils.html#106>`_ @@ -2138,10 +2144,10 @@ Index `strutils.html#141 <strutils.html#141>`_ `intVal`:idx: - `macros.html#122 <macros.html#122>`_ + `macros.html#123 <macros.html#123>`_ `intVal=`:idx: - `macros.html#128 <macros.html#128>`_ + `macros.html#129 <macros.html#129>`_ `is`:idx: `system.html#353 <system.html#353>`_ @@ -2226,7 +2232,7 @@ Index `kind`:idx: * `parsexml.html#110 <parsexml.html#110>`_ - * `macros.html#121 <macros.html#121>`_ + * `macros.html#122 <macros.html#122>`_ `l-values`:idx: `manual.html#107 <manual.html#107>`_ @@ -2245,13 +2251,13 @@ Index * `system.html#172 <system.html#172>`_ * `strtabs.html#109 <strtabs.html#109>`_ * `parsesql.html#107 <parsesql.html#107>`_ - * `macros.html#117 <macros.html#117>`_ + * `macros.html#118 <macros.html#118>`_ `Letters`:idx: `strutils.html#103 <strutils.html#103>`_ `letters`:idx: - `pegs.html#124 <pegs.html#124>`_ + `pegs.html#125 <pegs.html#125>`_ `li`:idx: `xmlgen.html#148 <xmlgen.html#148>`_ @@ -2353,16 +2359,16 @@ Index `xmlgen.html#150 <xmlgen.html#150>`_ `match`:idx: - * `regexprs.html#103 <regexprs.html#103>`_ - * `regexprs.html#104 <regexprs.html#104>`_ - * `pegs.html#132 <pegs.html#132>`_ - * `pegs.html#133 <pegs.html#133>`_ - - `matchLen`:idx: - * `regexprs.html#105 <regexprs.html#105>`_ + * `regexprs.html#106 <regexprs.html#106>`_ + * `regexprs.html#107 <regexprs.html#107>`_ * `pegs.html#134 <pegs.html#134>`_ * `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: * `system.html#318 <system.html#318>`_ * `system.html#444 <system.html#444>`_ @@ -2397,8 +2403,8 @@ Index `mysql.html#191 <mysql.html#191>`_ `MaxSubpatterns`:idx: - * `regexprs.html#102 <regexprs.html#102>`_ - * `pegs.html#131 <pegs.html#131>`_ + * `regexprs.html#105 <regexprs.html#105>`_ + * `pegs.html#132 <pegs.html#132>`_ `MAX_TINYINT_WIDTH`:idx: `mysql.html#190 <mysql.html#190>`_ @@ -2990,13 +2996,13 @@ Index `system.html#134 <system.html#134>`_ `natural`:idx: - `pegs.html#130 <pegs.html#130>`_ + `pegs.html#131 <pegs.html#131>`_ `neginf`:idx: `system.html#430 <system.html#430>`_ `nestList`:idx: - `macros.html#151 <macros.html#151>`_ + `macros.html#152 <macros.html#152>`_ `NET`:idx: `mysql.html#199 <mysql.html#199>`_ @@ -3042,38 +3048,38 @@ Index * `system.html#125 <system.html#125>`_ `newCall`:idx: - * `macros.html#149 <macros.html#149>`_ * `macros.html#150 <macros.html#150>`_ + * `macros.html#151 <macros.html#151>`_ `newFileStream`:idx: * `streams.html#120 <streams.html#120>`_ * `streams.html#121 <streams.html#121>`_ `newFloatLitNode`:idx: - `macros.html#142 <macros.html#142>`_ + `macros.html#143 <macros.html#143>`_ `newIdentNode`:idx: - * `macros.html#143 <macros.html#143>`_ * `macros.html#144 <macros.html#144>`_ + * `macros.html#145 <macros.html#145>`_ `newIntLitNode`:idx: - `macros.html#141 <macros.html#141>`_ + `macros.html#142 <macros.html#142>`_ + + `newLine`:idx: + `pegs.html#121 <pegs.html#121>`_ `newline`:idx: * `manual.html#121 <manual.html#121>`_ - * `pegs.html#119 <pegs.html#119>`_ - - `newLine`:idx: - `pegs.html#120 <pegs.html#120>`_ + * `pegs.html#120 <pegs.html#120>`_ `NewLines`:idx: `lexbase.html#102 <lexbase.html#102>`_ `newNimNode`:idx: - `macros.html#134 <macros.html#134>`_ + `macros.html#135 <macros.html#135>`_ `newNonTerminal`:idx: - `pegs.html#123 <pegs.html#123>`_ + `pegs.html#124 <pegs.html#124>`_ `newSeq`:idx: `system.html#167 <system.html#167>`_ @@ -3089,7 +3095,7 @@ Index * `strtabs.html#105 <strtabs.html#105>`_ `newStrLitNode`:idx: - `macros.html#140 <macros.html#140>`_ + `macros.html#141 <macros.html#141>`_ `next`:idx: * `parseopt.html#105 <parseopt.html#105>`_ @@ -3124,7 +3130,7 @@ Index `mysql.html#136 <mysql.html#136>`_ `nonterminal`:idx: - `pegs.html#122 <pegs.html#122>`_ + `pegs.html#123 <pegs.html#123>`_ `normalize`:idx: `strutils.html#118 <strutils.html#118>`_ @@ -3238,7 +3244,7 @@ Index `strtabs.html#110 <strtabs.html#110>`_ `parallelReplace`:idx: - `pegs.html#144 <pegs.html#144>`_ + `pegs.html#146 <pegs.html#146>`_ `param`:idx: `xmlgen.html#158 <xmlgen.html#158>`_ @@ -3268,7 +3274,7 @@ Index `strutils.html#142 <strutils.html#142>`_ `parsePeg`:idx: - `pegs.html#150 <pegs.html#150>`_ + `pegs.html#151 <pegs.html#151>`_ `parseSQL`:idx: `parsesql.html#109 <parsesql.html#109>`_ @@ -3403,7 +3409,7 @@ Index `libcurl.html#122 <libcurl.html#122>`_ `peg`:idx: - `pegs.html#151 <pegs.html#151>`_ + `pegs.html#152 <pegs.html#152>`_ `Pfd_set`:idx: `libcurl.html#138 <libcurl.html#138>`_ @@ -3771,16 +3777,16 @@ Index `system.html#412 <system.html#412>`_ `reBinary`:idx: - `regexprs.html#113 <regexprs.html#113>`_ + `regexprs.html#116 <regexprs.html#116>`_ `Recursive module dependancies`:idx: `manual.html#221 <manual.html#221>`_ `reEmail`:idx: - `regexprs.html#116 <regexprs.html#116>`_ + `regexprs.html#119 <regexprs.html#119>`_ `reFloat`:idx: - `regexprs.html#115 <regexprs.html#115>`_ + `regexprs.html#118 <regexprs.html#118>`_ `REFRESH_DES_KEY_FILE`:idx: `mysql.html#154 <mysql.html#154>`_ @@ -3828,13 +3834,13 @@ Index `nimrodc.html#112 <nimrodc.html#112>`_ `reHex`:idx: - `regexprs.html#112 <regexprs.html#112>`_ + `regexprs.html#115 <regexprs.html#115>`_ `reIdentifier`:idx: - `regexprs.html#109 <regexprs.html#109>`_ + `regexprs.html#112 <regexprs.html#112>`_ `reInteger`:idx: - `regexprs.html#111 <regexprs.html#111>`_ + `regexprs.html#114 <regexprs.html#114>`_ `removeDir`:idx: `os.html#158 <os.html#158>`_ @@ -3843,13 +3849,13 @@ Index `os.html#144 <os.html#144>`_ `reNatural`:idx: - `regexprs.html#110 <regexprs.html#110>`_ + `regexprs.html#113 <regexprs.html#113>`_ `renderSQL`:idx: `parsesql.html#110 <parsesql.html#110>`_ `reOctal`:idx: - `regexprs.html#114 <regexprs.html#114>`_ + `regexprs.html#117 <regexprs.html#117>`_ `repeatChar`:idx: `strutils.html#146 <strutils.html#146>`_ @@ -3857,7 +3863,7 @@ Index `replace`:idx: * `strutils.html#154 <strutils.html#154>`_ * `strutils.html#155 <strutils.html#155>`_ - * `pegs.html#143 <pegs.html#143>`_ + * `pegs.html#145 <pegs.html#145>`_ `replaceStr`:idx: * `strutils.html#122 <strutils.html#122>`_ @@ -3880,7 +3886,7 @@ Index `manual.html#192 <manual.html#192>`_ `reURL`:idx: - `regexprs.html#117 <regexprs.html#117>`_ + `regexprs.html#120 <regexprs.html#120>`_ `round`:idx: `math.html#121 <math.html#121>`_ @@ -4048,6 +4054,9 @@ Index * `system.html#230 <system.html#230>`_ * `system.html#231 <system.html#231>`_ + `simple assertions`:idx: + `regexprs.html#103 <regexprs.html#103>`_ + `simple statements`:idx: `manual.html#177 <manual.html#177>`_ @@ -4074,8 +4083,8 @@ Index * `strutils.html#127 <strutils.html#127>`_ * `strutils.html#133 <strutils.html#133>`_ * `strutils.html#134 <strutils.html#134>`_ - * `pegs.html#146 <pegs.html#146>`_ - * `pegs.html#147 <pegs.html#147>`_ + * `pegs.html#148 <pegs.html#148>`_ + * `pegs.html#149 <pegs.html#149>`_ `splitFile`:idx: `os.html#129 <os.html#129>`_ @@ -4611,7 +4620,7 @@ Index `startsWith`:idx: * `strutils.html#147 <strutils.html#147>`_ - * `pegs.html#141 <pegs.html#141>`_ + * `pegs.html#143 <pegs.html#143>`_ `statement macros`:idx: `tut2.html#112 <tut2.html#112>`_ @@ -4702,10 +4711,10 @@ Index `manual.html#152 <manual.html#152>`_ `strVal`:idx: - `macros.html#127 <macros.html#127>`_ + `macros.html#128 <macros.html#128>`_ `strVal=`:idx: - `macros.html#133 <macros.html#133>`_ + `macros.html#134 <macros.html#134>`_ `st_udf_args`:idx: `mysql.html#258 <mysql.html#258>`_ @@ -4751,10 +4760,10 @@ Index `dynlib.html#104 <dynlib.html#104>`_ `symbol`:idx: - `macros.html#124 <macros.html#124>`_ + `macros.html#125 <macros.html#125>`_ `symbol=`:idx: - `macros.html#130 <macros.html#130>`_ + `macros.html#131 <macros.html#131>`_ `syscall`:idx: `manual.html#172 <manual.html#172>`_ @@ -5114,7 +5123,7 @@ Index `strutils.html#145 <strutils.html#145>`_ `toStrLit`:idx: - `macros.html#145 <macros.html#145>`_ + `macros.html#146 <macros.html#146>`_ `toTitle`:idx: `unicode.html#113 <unicode.html#113>`_ @@ -5153,7 +5162,7 @@ Index * `tut1.html#121 <tut1.html#121>`_ `transformFile`:idx: - `pegs.html#145 <pegs.html#145>`_ + `pegs.html#147 <pegs.html#147>`_ `TRequestMethod`:idx: `cgi.html#105 <cgi.html#105>`_ @@ -5244,10 +5253,10 @@ Index `parsexml.html#106 <parsexml.html#106>`_ `typ`:idx: - `macros.html#126 <macros.html#126>`_ + `macros.html#127 <macros.html#127>`_ `typ=`:idx: - `macros.html#132 <macros.html#132>`_ + `macros.html#133 <macros.html#133>`_ `type`:idx: * `manual.html#102 <manual.html#102>`_ @@ -5363,7 +5372,7 @@ Index * `tut2.html#103 <tut2.html#103>`_ `verbose`:idx: - `regexprs.html#118 <regexprs.html#118>`_ + `regexprs.html#121 <regexprs.html#121>`_ `vertical tabulator`:idx: `manual.html#126 <manual.html#126>`_ @@ -5387,7 +5396,7 @@ Index `warning`:idx: * `manual.html#225 <manual.html#225>`_ * `manual.html#232 <manual.html#232>`_ - * `macros.html#138 <macros.html#138>`_ + * `macros.html#139 <macros.html#139>`_ `when`:idx: * `manual.html#185 <manual.html#185>`_ @@ -5400,7 +5409,7 @@ Index `strutils.html#102 <strutils.html#102>`_ `whitespace`:idx: - `pegs.html#126 <pegs.html#126>`_ + `pegs.html#127 <pegs.html#127>`_ `winTimeToUnixTime`:idx: `times.html#118 <times.html#118>`_ diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim index c029f92a2..21205bdb2 100755 --- a/lib/pure/pegs.nim +++ b/lib/pure/pegs.nim @@ -42,7 +42,7 @@ type pkSequence, ## a b c ... --> Internal DSL: peg(a, b, c) pkOrderedChoice, ## a / b / ... --> Internal DSL: a / b or /[a, b, c] 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) pkGreedyRepSet, ## [set]* (superop) pkGreedyAny, ## .* or _* (superop) @@ -50,6 +50,7 @@ type pkAndPredicate, ## &a --> Internal DSL: &a pkNotPredicate, ## !a --> Internal DSL: !a pkCapture, ## {a} --> Internal DSL: capture(a) + pkSearch, ## @a --> Internal DSL: @a pkRule, ## a <- b pkList ## a, b TNonTerminalFlag = enum @@ -174,7 +175,24 @@ proc `*`*(a: TPeg): TPeg = else: result.kind = pkGreedyRep 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 = ## constructs a "greedy positive repetition" with the PEG `a` return sequence(a, *a) @@ -271,6 +289,125 @@ const MaxSubpatterns* = 10 ## defines the maximum number of subpatterns that ## 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 ------------------------------------------- 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) if result >= 0: break 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: result = 0 while true: @@ -607,123 +755,6 @@ proc split*(s: string, sep: TPeg): seq[string] {.noSideEffect.} = ## Splits the string `s` into substrings. 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 ------------------------------------------------- type @@ -751,6 +782,7 @@ type tkAmp, ## '&' tkNot, ## '!' tkOption, ## '?' + tkAt, ## '@' tkBuiltin, ## \identifier tkEscaped ## \\ @@ -772,7 +804,7 @@ const tokKindToStr: array[TTokKind, string] = [ "invalid", "[EOF]", ".", "_", "identifier", "string literal", "character set", "(", ")", "{", "}", "<-", "/", "*", "+", "&", "!", "?", - "built-in", "escaped" + "@", "built-in", "escaped" ] proc HandleCR(L: var TPegLexer, pos: int): int = @@ -1063,6 +1095,10 @@ proc getTok(c: var TPegLexer, tok: var TToken) = tok.kind = tkAmp inc(c.bufpos) add(tok.literal, '!') + of '@': + tok.kind = tkAt + inc(c.bufpos) + add(tok.literal, '@') else: add(tok.literal, c.buf[c.bufpos]) inc(c.bufpos) @@ -1118,6 +1154,9 @@ proc primary(p: var TPegParser): TPeg = of tkNot: getTok(p) return !primary(p) + of tkAt: + getTok(p) + return @primary(p) else: nil case p.tok.kind of tkIdentifier: @@ -1187,7 +1226,7 @@ proc seqExpr(p: var TPegParser): TPeg = result = primary(p) while true: case p.tok.kind - of tkAmp, tkNot, tkStringLit, tkCharset, tkParLe, tkCurlyLe, + of tkAmp, tkNot, tkAt, tkStringLit, tkCharset, tkParLe, tkCurlyLe, tkAny, tkAnyRune, tkBuiltin, tkEscaped: result = sequence(result, primary(p)) of tkIdentifier: @@ -1261,6 +1300,7 @@ proc peg*(pattern: string): TPeg = result = parsePeg(pattern, "pattern") when isMainModule: + assert match("(a b c)", peg"'(' @ ')'") assert match("W_HI_Le", peg"\y 'while'") assert(not match("W_HI_L", peg"\y 'while'")) assert(not match("W_HI_Le", peg"\y v'while'")) @@ -1315,6 +1355,11 @@ when isMainModule: """ assert($g2 == "((A B) / (C D))") 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}") + if "aaaaaa" =~ peg"'aa' !. / ({'a'})+": + assert matches[0] == "a" + else: + assert false diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index 1edddecd9..2a53d7660 100755 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -44,15 +44,13 @@ proc runeLenAt*(s: string, i: int): int = template fastRuneAt*(s: string, i: int, result: expr, 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. - when not defined(ones): - template ones(n: expr): expr = ((1 shl n)-1) - if ord(s[i]) <=% 127: result = TRune(ord(s[i])) when doInc: inc(i) elif ord(s[i]) shr 5 == 0b110: 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) elif ord(s[i]) shr 4 == 0b1110: assert(ord(s[i+1]) shr 6 == 0b10) diff --git a/nim/llvmdata.pas b/nim/llvmdata.pas new file mode 100755 index 000000000..a8ae0f311 --- /dev/null +++ b/nim/llvmdata.pas @@ -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. + diff --git a/nim/pbraces.pas b/nim/pbraces.pas index d362fac65..2e10c50f2 100755 --- a/nim/pbraces.pas +++ b/nim/pbraces.pas @@ -146,8 +146,7 @@ begin end; end; -procedure qualifiedIdentListAux(var p: TParser; endTok: TTokType; - result: PNode); +procedure qualifiedIdentListAux(var p: TParser; endTok: TTokType; result: PNode); var a: PNode; begin @@ -216,16 +215,6 @@ begin eat(p, tkParRi); 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; begin case p.tok.tokType of @@ -542,7 +531,7 @@ begin optInd(p, result); while (p.tok.tokType = tkSymbol) or (p.tok.tokType = tkAccent) do begin a := parseIdentColonEquals(p, {@set}[]); - addSon(result, a); + addSon(result, a); if p.tok.tokType <> tkComma then break; getTok(p); optInd(p, a) @@ -729,12 +718,12 @@ begin end end; -function parseImportStmt(var p: TParser): PNode; +function parseImportOrIncludeStmt(var p: TParser; kind: TNodeKind): PNode; var a: PNode; begin - result := newNodeP(nkImportStmt, p); - getTok(p); // skip `import` + result := newNodeP(kind, p); + getTok(p); // skip `import` or `include` optInd(p, result); while true do begin case p.tok.tokType of @@ -764,41 +753,6 @@ begin 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; var a: PNode; @@ -1150,6 +1104,24 @@ begin indAndComment(p, result); // XXX: special extension! 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; var a, b: PNode; @@ -1379,9 +1351,9 @@ begin tkBreak: result := parseBreakOrContinue(p, nkBreakStmt); tkContinue: result := parseBreakOrContinue(p, nkContinueStmt); tkCurlyDotLe: result := parsePragma(p); - tkImport: result := parseImportStmt(p); + tkImport: result := parseImportOrIncludeStmt(p, nkImportStmt); tkFrom: result := parseFromStmt(p); - tkInclude: result := parseIncludeStmt(p); + tkInclude: result := parseImportOrIncludeStmt(p, nkIncludeStmt); tkComment: result := newCommentStmt(p); else begin if isExprStart(p) then @@ -1394,6 +1366,24 @@ begin skipComment(p, result); 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; begin case p.tok.tokType of @@ -1410,8 +1400,9 @@ begin tkMacro: result := parseRoutine(p, nkMacroDef); tkTemplate: result := parseRoutine(p, nkTemplateDef); tkConverter: result := parseRoutine(p, nkConverterDef); - tkType: result := parseSection(p, nkTypeSection, parseTypeDef); - tkConst: result := parseSection(p, nkConstSection, parseConstant); + tkType, tkEnum, tkObject, tkTuple: + result := parseTypeAlias(p, nkTypeSection, parseTypeDef); + tkConst: result := parseConstSection(p); tkWhen: result := parseIfOrWhen(p, nkWhenStmt); tkVar: result := parseSection(p, nkVarSection, parseVariable); else result := simpleStmt(p); @@ -1422,15 +1413,13 @@ function parseStmt(var p: TParser): PNode; var a: PNode; begin - if p.tok.tokType = tkInd then begin + if p.tok.tokType = tkCurlyLe then begin result := newNodeP(nkStmtList, p); - pushInd(p.lex^, p.tok.indent); getTok(p); while true do begin case p.tok.tokType of - tkSad: getTok(p); - tkEof: break; - tkDed: begin getTok(p); break end; + tkSad, tkInd, tkDed: getTok(p); + tkEof, tkCurlyRi: break; else begin a := complexOrSimpleStmt(p); if a = nil then break; @@ -1438,7 +1427,7 @@ begin end end end; - popInd(p.lex^); + eat(p, tkCurlyRi); end else begin // the case statement is only needed for better error messages: @@ -1451,7 +1440,7 @@ begin else begin result := simpleStmt(p); 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 @@ -1464,8 +1453,7 @@ begin result := newNodeP(nkStmtList, p); while true do begin case p.tok.tokType of - tkSad: getTok(p); - tkDed, tkInd: parMessage(p, errInvalidIndentation); + tkDed, tkInd, tkSad: getTok(p); tkEof: break; else begin a := complexOrSimpleStmt(p); @@ -1481,11 +1469,7 @@ begin result := nil; while true do begin case p.tok.tokType of - tkSad: getTok(p); - tkDed, tkInd: begin - parMessage(p, errInvalidIndentation); - break; - end; + tkDed, tkInd, tkSad: getTok(p); tkEof: break; else begin result := complexOrSimpleStmt(p); diff --git a/nim/pendx.pas b/nim/pendx.pas new file mode 100755 index 000000000..e23229e28 --- /dev/null +++ b/nim/pendx.pas @@ -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. diff --git a/nim/pnimsyn.pas b/nim/pnimsyn.pas index bf964fda1..eeaf2a6e9 100755 --- a/nim/pnimsyn.pas +++ b/nim/pnimsyn.pas @@ -72,6 +72,7 @@ procedure optSad(var p: TParser); procedure optInd(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 accExpr(var p: TParser): PNode; @@ -1069,12 +1070,12 @@ begin end end; -function parseImportStmt(var p: TParser): PNode; +function parseImportOrIncludeStmt(var p: TParser; kind: TNodeKind): PNode; var a: PNode; begin - result := newNodeP(nkImportStmt, p); - getTok(p); // skip `import` + result := newNodeP(kind, p); + getTok(p); // skip `import` or `include` optInd(p, result); while true do begin case p.tok.tokType of @@ -1104,42 +1105,6 @@ begin 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; var a: PNode; @@ -1717,9 +1682,9 @@ begin tkBreak: result := parseBreakOrContinue(p, nkBreakStmt); tkContinue: result := parseBreakOrContinue(p, nkContinueStmt); tkCurlyDotLe: result := parsePragma(p); - tkImport: result := parseImportStmt(p); + tkImport: result := parseImportOrIncludeStmt(p, nkImportStmt); tkFrom: result := parseFromStmt(p); - tkInclude: result := parseIncludeStmt(p); + tkInclude: result := parseImportOrIncludeStmt(p, nkIncludeStmt); tkComment: result := newCommentStmt(p); else begin if isExprStart(p) then diff --git a/nim/semgnrc.pas b/nim/semgnrc.pas new file mode 100755 index 000000000..ee905d444 --- /dev/null +++ b/nim/semgnrc.pas @@ -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; diff --git a/nim/semtempl.pas b/nim/semtempl.pas index e639960d3..fc7e12a73 100755 --- a/nim/semtempl.pas +++ b/nim/semtempl.pas @@ -147,7 +147,8 @@ begin end end; -function resolveTemplateParams(c: PContext; n: PNode; withinBind: bool): PNode; +function resolveTemplateParams(c: PContext; n: PNode; withinBind: bool; + var toBind: TIntSet): PNode; var i: int; s: PSym; @@ -155,7 +156,7 @@ begin if n = nil then begin result := nil; exit end; case n.kind of 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); if (s <> nil) then begin result := newSymNode(s); @@ -165,17 +166,18 @@ begin result := n end else begin + IntSetIncl(toBind, n.ident.id); result := symChoice(c, n, lookup(c, n)) end end; nkSym..nkNilLit: // atom result := n; nkBind: - result := resolveTemplateParams(c, n.sons[0], true); + result := resolveTemplateParams(c, n.sons[0], true, toBind); else begin result := n; 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; @@ -211,6 +213,7 @@ end; function semTemplateDef(c: PContext; n: PNode): PNode; var s: PSym; + toBind: TIntSet; begin if c.p.owner.kind = skModule then begin s := semIdentVis(c, skTemplate, n.sons[0], {@set}[sfStar]); @@ -248,7 +251,8 @@ begin addParams(c, s.typ.n); // 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 n.sons[codePos] := transformToExpr(n.sons[codePos]); diff --git a/nim/syntaxes.pas b/nim/syntaxes.pas index 19035028e..158ab8ea2 100755 --- a/nim/syntaxes.pas +++ b/nim/syntaxes.pas @@ -15,7 +15,7 @@ interface uses nsystem, strutils, llstream, ast, astalgo, idents, scanner, options, msgs, - pnimsyn, ptmplsyn, filters, rnimsyn; + pnimsyn, pbraces, ptmplsyn, filters, rnimsyn; type TFilterKind = (filtNone, filtTemplate, filtReplace, filtStrip); @@ -68,8 +68,8 @@ function parseAll(var p: TParsers): PNode; begin case p.skin of 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); end end; @@ -78,8 +78,8 @@ function parseTopLevelStmt(var p: TParsers): PNode; begin case p.skin of 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); end end; diff --git a/nim/vis.pas b/nim/vis.pas new file mode 100755 index 000000000..b8ba0fc5b --- /dev/null +++ b/nim/vis.pas @@ -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. diff --git a/tools/nimweb.nim b/tools/nimweb.nim index 249ec5f61..05b575d16 100755 --- a/tools/nimweb.nim +++ b/tools/nimweb.nim @@ -178,7 +178,7 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) = Exec("pdflatex " & changeFileExt(d, "tex")) Exec("pdflatex " & changeFileExt(d, "tex")) # delete all the crappy temporary files: - var pdf = extractFileTrunk(d) & ".pdf" + var pdf = splitFile(d).name & ".pdf" moveFile(destPath / pdf, pdf) removeFile(changeFileExt(pdf, "aux")) if existsFile(changeFileExt(pdf, "toc")): diff --git a/web/question.txt b/web/question.txt index 83edfda72..17a1abfcf 100755 --- a/web/question.txt +++ b/web/question.txt @@ -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 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? ----------------------- |