explicit types for generic routines
This commit is contained in:
parent
e90665bff2
commit
6c20509121
25 changed files with 411 additions and 343 deletions
130
doc/intern.txt
130
doc/intern.txt
|
|
@ -114,6 +114,71 @@ Thus we need to serialize this graph as RTTI for C code generation.
|
||||||
Look at the file ``lib/system/hti.nim`` for more information.
|
Look at the file ``lib/system/hti.nim`` for more information.
|
||||||
|
|
||||||
|
|
||||||
|
The compiler's architecture
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Nimrod uses the classic compiler architecture: A scanner feds tokens to a
|
||||||
|
parser. The parser builds a syntax tree that is used by the code generator.
|
||||||
|
This syntax tree is the interface between the parser and the code generator.
|
||||||
|
It is essential to understand most of the compiler's code.
|
||||||
|
|
||||||
|
In order to compile Nimrod correctly, type-checking has to be seperated from
|
||||||
|
parsing. Otherwise generics cannot work.
|
||||||
|
|
||||||
|
.. include:: filelist.txt
|
||||||
|
|
||||||
|
|
||||||
|
The syntax tree
|
||||||
|
---------------
|
||||||
|
The synax tree consists of nodes which may have an arbitrary number of
|
||||||
|
children. Types and symbols are represented by other nodes, because they
|
||||||
|
may contain cycles. The AST changes its shape after semantic checking. This
|
||||||
|
is needed to make life easier for the code generators. See the "ast" module
|
||||||
|
for the type definitions. The `macros <macros.html>`_ module contains many
|
||||||
|
examples how the AST represents each syntactic structure.
|
||||||
|
|
||||||
|
|
||||||
|
How the RTL is compiled
|
||||||
|
=======================
|
||||||
|
|
||||||
|
The ``system`` module contains the part of the RTL which needs support by
|
||||||
|
compiler magic (and the stuff that needs to be in it because the spec
|
||||||
|
says so). The C code generator generates the C code for it just like any other
|
||||||
|
module. However, calls to some procedures like ``addInt`` are inserted by
|
||||||
|
the CCG. Therefore the module ``magicsys`` contains a table (``compilerprocs``)
|
||||||
|
with all symbols that are marked as ``compilerproc``. ``compilerprocs`` are
|
||||||
|
needed by the code generator. A ``magic`` proc is not the same as a
|
||||||
|
``compilerproc``: A ``magic`` is a proc that needs compiler magic for its
|
||||||
|
semantic checking, a ``compilerproc`` is a proc that is used by the code
|
||||||
|
generator.
|
||||||
|
|
||||||
|
|
||||||
|
Debugging Nimrod's memory management
|
||||||
|
====================================
|
||||||
|
|
||||||
|
The following paragraphs are mostly a reminder for myself. Things to keep
|
||||||
|
in mind:
|
||||||
|
|
||||||
|
* Segmentation faults can have multiple reasons: One that is frequently
|
||||||
|
forgotten is that *stack overflow* can trigger one!
|
||||||
|
* If an assertion in Nimrod's memory manager or GC fails, the stack trace
|
||||||
|
keeps allocating memory! Thus a stack overflow may happen, hiding the
|
||||||
|
real issue.
|
||||||
|
* What seem to be C code generation problems is often a bug resulting from
|
||||||
|
not producing prototypes, so that some types default to ``cint``. Testing
|
||||||
|
without the ``-w`` option helps!
|
||||||
|
|
||||||
|
|
||||||
|
Generation of dynamic link libraries
|
||||||
|
====================================
|
||||||
|
|
||||||
|
Generation of dynamic link libraries or shared libraries is not difficult; the
|
||||||
|
underlying C compiler already does all the hard work for us. The problem is the
|
||||||
|
common runtime library, especially the memory manager. Note that Borland's
|
||||||
|
Delphi had exactly the same problem. The workaround is to not link the GC with
|
||||||
|
the Dll and provide an extra runtime dll that needs to be initialized.
|
||||||
|
|
||||||
|
|
||||||
The Garbage Collector
|
The Garbage Collector
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
|
|
@ -216,71 +281,6 @@ the check whether the ref is on the stack is very cheap (only two
|
||||||
comparisons).
|
comparisons).
|
||||||
|
|
||||||
|
|
||||||
The compiler's architecture
|
|
||||||
===========================
|
|
||||||
|
|
||||||
Nimrod uses the classic compiler architecture: A scanner feds tokens to a
|
|
||||||
parser. The parser builds a syntax tree that is used by the code generator.
|
|
||||||
This syntax tree is the interface between the parser and the code generator.
|
|
||||||
It is essential to understand most of the compiler's code.
|
|
||||||
|
|
||||||
In order to compile Nimrod correctly, type-checking has to be seperated from
|
|
||||||
parsing. Otherwise generics would not work.
|
|
||||||
|
|
||||||
.. include:: filelist.txt
|
|
||||||
|
|
||||||
|
|
||||||
The syntax tree
|
|
||||||
---------------
|
|
||||||
The synax tree consists of nodes which may have an arbitrary number of
|
|
||||||
children. Types and symbols are represented by other nodes, because they
|
|
||||||
may contain cycles. The AST changes its shape after semantic checking. This
|
|
||||||
is needed to make life easier for the code generators. See the "ast" module
|
|
||||||
for the type definitions. The `macros <macros.html>`_ module contains many
|
|
||||||
examples how the AST represents each syntactic structure.
|
|
||||||
|
|
||||||
|
|
||||||
How the RTL is compiled
|
|
||||||
=======================
|
|
||||||
|
|
||||||
The ``system`` module contains the part of the RTL which needs support by
|
|
||||||
compiler magic (and the stuff that needs to be in it because the spec
|
|
||||||
says so). The C code generator generates the C code for it just like any other
|
|
||||||
module. However, calls to some procedures like ``addInt`` are inserted by
|
|
||||||
the CCG. Therefore the module ``magicsys`` contains a table (``compilerprocs``)
|
|
||||||
with all symbols that are marked as ``compilerproc``. ``compilerprocs`` are
|
|
||||||
needed by the code generator. A ``magic`` proc is not the same as a
|
|
||||||
``compilerproc``: A ``magic`` is a proc that needs compiler magic for its
|
|
||||||
semantic checking, a ``compilerproc`` is a proc that is used by the code
|
|
||||||
generator.
|
|
||||||
|
|
||||||
|
|
||||||
Debugging Nimrod's memory management
|
|
||||||
====================================
|
|
||||||
|
|
||||||
The following paragraphs are mostly a reminder for myself. Things to keep
|
|
||||||
in mind:
|
|
||||||
|
|
||||||
* Segmentation faults can have multiple reasons: One that is frequently
|
|
||||||
forgotten is that *stack overflow* can trigger one!
|
|
||||||
* If an assertion in Nimrod's memory manager or GC fails, the stack trace
|
|
||||||
keeps allocating memory! Thus a stack overflow may happen, hiding the
|
|
||||||
real issue.
|
|
||||||
* What seem to be C code generation problems is often a bug resulting from
|
|
||||||
not producing prototypes, so that some types default to ``cint``. Testing
|
|
||||||
without the ``-w`` option helps!
|
|
||||||
|
|
||||||
|
|
||||||
Generation of dynamic link libraries
|
|
||||||
====================================
|
|
||||||
|
|
||||||
Generation of dynamic link libraries or shared libraries is not difficult; the
|
|
||||||
underlying C compiler already does all the hard work for us. The problem is the
|
|
||||||
common runtime library, especially the memory manager. Note that Borland's
|
|
||||||
Delphi had exactly the same problem. The workaround is to not link the GC with
|
|
||||||
the Dll and provide an extra runtime dll that needs to be initialized.
|
|
||||||
|
|
||||||
|
|
||||||
Code generation for closures
|
Code generation for closures
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,7 @@ Database support
|
||||||
for other databases too.
|
for other databases too.
|
||||||
|
|
||||||
* `db_sqlite <db_sqlite.html>`_
|
* `db_sqlite <db_sqlite.html>`_
|
||||||
A higher level mySQL database wrapper. The same interface is implemented
|
A higher level SQLite database wrapper. The same interface is implemented
|
||||||
for other databases too.
|
for other databases too.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
138
doc/theindex.txt
138
doc/theindex.txt
|
|
@ -276,10 +276,10 @@ Index
|
||||||
`ropes.html#115 <ropes.html#115>`_
|
`ropes.html#115 <ropes.html#115>`_
|
||||||
|
|
||||||
`[]`:idx:
|
`[]`:idx:
|
||||||
`xmltree.html#114 <xmltree.html#114>`_
|
`graphics.html#111 <graphics.html#111>`_
|
||||||
|
|
||||||
`[]`:idx:
|
`[]`:idx:
|
||||||
`graphics.html#111 <graphics.html#111>`_
|
`xmltree.html#114 <xmltree.html#114>`_
|
||||||
|
|
||||||
`[]=`:idx:
|
`[]=`:idx:
|
||||||
`strtabs.html#106 <strtabs.html#106>`_
|
`strtabs.html#106 <strtabs.html#106>`_
|
||||||
|
|
@ -731,12 +731,6 @@ Index
|
||||||
`clonglong`:idx:
|
`clonglong`:idx:
|
||||||
`system.html#388 <system.html#388>`_
|
`system.html#388 <system.html#388>`_
|
||||||
|
|
||||||
`Close`:idx:
|
|
||||||
* `system.html#512 <system.html#512>`_
|
|
||||||
* `db_postgres.html#117 <db_postgres.html#117>`_
|
|
||||||
* `db_mysql.html#117 <db_mysql.html#117>`_
|
|
||||||
* `db_sqlite.html#117 <db_sqlite.html#117>`_
|
|
||||||
|
|
||||||
`close`:idx:
|
`close`:idx:
|
||||||
* `sockets.html#121 <sockets.html#121>`_
|
* `sockets.html#121 <sockets.html#121>`_
|
||||||
* `lexbase.html#105 <lexbase.html#105>`_
|
* `lexbase.html#105 <lexbase.html#105>`_
|
||||||
|
|
@ -746,8 +740,14 @@ Index
|
||||||
* `zipfiles.html#103 <zipfiles.html#103>`_
|
* `zipfiles.html#103 <zipfiles.html#103>`_
|
||||||
* `httpserver.html#106 <httpserver.html#106>`_
|
* `httpserver.html#106 <httpserver.html#106>`_
|
||||||
|
|
||||||
|
`Close`:idx:
|
||||||
|
* `system.html#513 <system.html#513>`_
|
||||||
|
* `db_postgres.html#117 <db_postgres.html#117>`_
|
||||||
|
* `db_mysql.html#117 <db_mysql.html#117>`_
|
||||||
|
* `db_sqlite.html#117 <db_sqlite.html#117>`_
|
||||||
|
|
||||||
`CloseFile`:idx:
|
`CloseFile`:idx:
|
||||||
`system.html#511 <system.html#511>`_
|
`system.html#512 <system.html#512>`_
|
||||||
|
|
||||||
`closure`:idx:
|
`closure`:idx:
|
||||||
`manual.html#177 <manual.html#177>`_
|
`manual.html#177 <manual.html#177>`_
|
||||||
|
|
@ -1350,8 +1350,8 @@ Index
|
||||||
`system.html#392 <system.html#392>`_
|
`system.html#392 <system.html#392>`_
|
||||||
|
|
||||||
`cstringArrayToSeq`:idx:
|
`cstringArrayToSeq`:idx:
|
||||||
* `system.html#539 <system.html#539>`_
|
|
||||||
* `system.html#540 <system.html#540>`_
|
* `system.html#540 <system.html#540>`_
|
||||||
|
* `system.html#541 <system.html#541>`_
|
||||||
|
|
||||||
`CSV`:idx:
|
`CSV`:idx:
|
||||||
`parsecsv.html#101 <parsecsv.html#101>`_
|
`parsecsv.html#101 <parsecsv.html#101>`_
|
||||||
|
|
@ -1777,8 +1777,7 @@ Index
|
||||||
* `strutils.html#157 <strutils.html#157>`_
|
* `strutils.html#157 <strutils.html#157>`_
|
||||||
|
|
||||||
`deleteStr`:idx:
|
`deleteStr`:idx:
|
||||||
* `strutils.html#124 <strutils.html#124>`_
|
`strutils.html#124 <strutils.html#124>`_
|
||||||
* `strutils.html#158 <strutils.html#158>`_
|
|
||||||
|
|
||||||
`dfn`:idx:
|
`dfn`:idx:
|
||||||
`xmlgen.html#125 <xmlgen.html#125>`_
|
`xmlgen.html#125 <xmlgen.html#125>`_
|
||||||
|
|
@ -1894,7 +1893,7 @@ Index
|
||||||
* `db_sqlite.html#104 <db_sqlite.html#104>`_
|
* `db_sqlite.html#104 <db_sqlite.html#104>`_
|
||||||
|
|
||||||
`editDistance`:idx:
|
`editDistance`:idx:
|
||||||
`strutils.html#166 <strutils.html#166>`_
|
`strutils.html#165 <strutils.html#165>`_
|
||||||
|
|
||||||
`EDivByZero`:idx:
|
`EDivByZero`:idx:
|
||||||
`system.html#147 <system.html#147>`_
|
`system.html#147 <system.html#147>`_
|
||||||
|
|
@ -2020,7 +2019,7 @@ Index
|
||||||
`endb.html#102 <endb.html#102>`_
|
`endb.html#102 <endb.html#102>`_
|
||||||
|
|
||||||
`EndOfFile`:idx:
|
`EndOfFile`:idx:
|
||||||
* `system.html#513 <system.html#513>`_
|
* `system.html#514 <system.html#514>`_
|
||||||
* `lexbase.html#101 <lexbase.html#101>`_
|
* `lexbase.html#101 <lexbase.html#101>`_
|
||||||
|
|
||||||
`endsWith`:idx:
|
`endsWith`:idx:
|
||||||
|
|
@ -2132,7 +2131,7 @@ Index
|
||||||
|
|
||||||
`escape`:idx:
|
`escape`:idx:
|
||||||
* `manual.html#133 <manual.html#133>`_
|
* `manual.html#133 <manual.html#133>`_
|
||||||
* `strutils.html#163 <strutils.html#163>`_
|
* `strutils.html#162 <strutils.html#162>`_
|
||||||
* `xmltree.html#122 <xmltree.html#122>`_
|
* `xmltree.html#122 <xmltree.html#122>`_
|
||||||
|
|
||||||
`escape sequences`:idx:
|
`escape sequences`:idx:
|
||||||
|
|
@ -2373,7 +2372,7 @@ Index
|
||||||
`mysql.html#218 <mysql.html#218>`_
|
`mysql.html#218 <mysql.html#218>`_
|
||||||
|
|
||||||
`fileHandle`:idx:
|
`fileHandle`:idx:
|
||||||
`system.html#538 <system.html#538>`_
|
`system.html#539 <system.html#539>`_
|
||||||
|
|
||||||
`fileNewer`:idx:
|
`fileNewer`:idx:
|
||||||
`os.html#119 <os.html#119>`_
|
`os.html#119 <os.html#119>`_
|
||||||
|
|
@ -2433,7 +2432,7 @@ Index
|
||||||
`macros.html#130 <macros.html#130>`_
|
`macros.html#130 <macros.html#130>`_
|
||||||
|
|
||||||
`FlushFile`:idx:
|
`FlushFile`:idx:
|
||||||
`system.html#515 <system.html#515>`_
|
`system.html#516 <system.html#516>`_
|
||||||
|
|
||||||
`for`:idx:
|
`for`:idx:
|
||||||
* `manual.html#214 <manual.html#214>`_
|
* `manual.html#214 <manual.html#214>`_
|
||||||
|
|
@ -2594,10 +2593,10 @@ Index
|
||||||
`os.html#162 <os.html#162>`_
|
`os.html#162 <os.html#162>`_
|
||||||
|
|
||||||
`getFilePos`:idx:
|
`getFilePos`:idx:
|
||||||
`system.html#535 <system.html#535>`_
|
`system.html#536 <system.html#536>`_
|
||||||
|
|
||||||
`getFileSize`:idx:
|
`getFileSize`:idx:
|
||||||
* `system.html#527 <system.html#527>`_
|
* `system.html#528 <system.html#528>`_
|
||||||
* `os.html#171 <os.html#171>`_
|
* `os.html#171 <os.html#171>`_
|
||||||
|
|
||||||
`getFreeMem`:idx:
|
`getFreeMem`:idx:
|
||||||
|
|
@ -2866,13 +2865,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>`_
|
||||||
|
|
||||||
`htmlTag`:idx:
|
`htmlTag`:idx:
|
||||||
* `htmlparser.html#105 <htmlparser.html#105>`_
|
* `htmlparser.html#105 <htmlparser.html#105>`_
|
||||||
* `htmlparser.html#106 <htmlparser.html#106>`_
|
* `htmlparser.html#106 <htmlparser.html#106>`_
|
||||||
|
|
@ -2914,24 +2913,24 @@ Index
|
||||||
`ident=`:idx:
|
`ident=`:idx:
|
||||||
`macros.html#132 <macros.html#132>`_
|
`macros.html#132 <macros.html#132>`_
|
||||||
|
|
||||||
`IdentChars`:idx:
|
|
||||||
`strutils.html#105 <strutils.html#105>`_
|
|
||||||
|
|
||||||
`identChars`:idx:
|
`identChars`:idx:
|
||||||
`pegs.html#132 <pegs.html#132>`_
|
`pegs.html#132 <pegs.html#132>`_
|
||||||
|
|
||||||
|
`IdentChars`:idx:
|
||||||
|
`strutils.html#105 <strutils.html#105>`_
|
||||||
|
|
||||||
`identifier`:idx:
|
`identifier`:idx:
|
||||||
`manual.html#105 <manual.html#105>`_
|
`manual.html#105 <manual.html#105>`_
|
||||||
|
|
||||||
`Identifiers`:idx:
|
`Identifiers`:idx:
|
||||||
`manual.html#116 <manual.html#116>`_
|
`manual.html#116 <manual.html#116>`_
|
||||||
|
|
||||||
`IdentStartChars`:idx:
|
|
||||||
`strutils.html#106 <strutils.html#106>`_
|
|
||||||
|
|
||||||
`identStartChars`:idx:
|
`identStartChars`:idx:
|
||||||
`pegs.html#133 <pegs.html#133>`_
|
`pegs.html#133 <pegs.html#133>`_
|
||||||
|
|
||||||
|
`IdentStartChars`:idx:
|
||||||
|
`strutils.html#106 <strutils.html#106>`_
|
||||||
|
|
||||||
`if`:idx:
|
`if`:idx:
|
||||||
`manual.html#189 <manual.html#189>`_
|
`manual.html#189 <manual.html#189>`_
|
||||||
|
|
||||||
|
|
@ -3018,7 +3017,7 @@ Index
|
||||||
* `db_sqlite.html#115 <db_sqlite.html#115>`_
|
* `db_sqlite.html#115 <db_sqlite.html#115>`_
|
||||||
|
|
||||||
`insertSep`:idx:
|
`insertSep`:idx:
|
||||||
`strutils.html#162 <strutils.html#162>`_
|
`strutils.html#161 <strutils.html#161>`_
|
||||||
|
|
||||||
`int`:idx:
|
`int`:idx:
|
||||||
`system.html#101 <system.html#101>`_
|
`system.html#101 <system.html#101>`_
|
||||||
|
|
@ -3208,8 +3207,8 @@ Index
|
||||||
`nimrodc.html#103 <nimrodc.html#103>`_
|
`nimrodc.html#103 <nimrodc.html#103>`_
|
||||||
|
|
||||||
`lines`:idx:
|
`lines`:idx:
|
||||||
* `system.html#536 <system.html#536>`_
|
|
||||||
* `system.html#537 <system.html#537>`_
|
* `system.html#537 <system.html#537>`_
|
||||||
|
* `system.html#538 <system.html#538>`_
|
||||||
|
|
||||||
`lineTrace`:idx:
|
`lineTrace`:idx:
|
||||||
`nimrodc.html#105 <nimrodc.html#105>`_
|
`nimrodc.html#105 <nimrodc.html#105>`_
|
||||||
|
|
@ -3233,13 +3232,13 @@ Index
|
||||||
`LoadLib`:idx:
|
`LoadLib`:idx:
|
||||||
`dynlib.html#102 <dynlib.html#102>`_
|
`dynlib.html#102 <dynlib.html#102>`_
|
||||||
|
|
||||||
`loadXML`:idx:
|
|
||||||
`xmldomparser.html#104 <xmldomparser.html#104>`_
|
|
||||||
|
|
||||||
`loadXml`:idx:
|
`loadXml`:idx:
|
||||||
* `xmlparser.html#104 <xmlparser.html#104>`_
|
* `xmlparser.html#104 <xmlparser.html#104>`_
|
||||||
* `xmlparser.html#105 <xmlparser.html#105>`_
|
* `xmlparser.html#105 <xmlparser.html#105>`_
|
||||||
|
|
||||||
|
`loadXML`:idx:
|
||||||
|
`xmldomparser.html#104 <xmldomparser.html#104>`_
|
||||||
|
|
||||||
`loadXMLFile`:idx:
|
`loadXMLFile`:idx:
|
||||||
`xmldomparser.html#105 <xmldomparser.html#105>`_
|
`xmldomparser.html#105 <xmldomparser.html#105>`_
|
||||||
|
|
||||||
|
|
@ -3965,12 +3964,12 @@ Index
|
||||||
`nan`:idx:
|
`nan`:idx:
|
||||||
`system.html#441 <system.html#441>`_
|
`system.html#441 <system.html#441>`_
|
||||||
|
|
||||||
`natural`:idx:
|
|
||||||
`pegs.html#135 <pegs.html#135>`_
|
|
||||||
|
|
||||||
`Natural`:idx:
|
`Natural`:idx:
|
||||||
`system.html#134 <system.html#134>`_
|
`system.html#134 <system.html#134>`_
|
||||||
|
|
||||||
|
`natural`:idx:
|
||||||
|
`pegs.html#135 <pegs.html#135>`_
|
||||||
|
|
||||||
`neginf`:idx:
|
`neginf`:idx:
|
||||||
`system.html#440 <system.html#440>`_
|
`system.html#440 <system.html#440>`_
|
||||||
|
|
||||||
|
|
@ -4056,13 +4055,13 @@ Index
|
||||||
`newIntLitNode`:idx:
|
`newIntLitNode`:idx:
|
||||||
`macros.html#142 <macros.html#142>`_
|
`macros.html#142 <macros.html#142>`_
|
||||||
|
|
||||||
|
`newLine`:idx:
|
||||||
|
`pegs.html#122 <pegs.html#122>`_
|
||||||
|
|
||||||
`newline`:idx:
|
`newline`:idx:
|
||||||
* `manual.html#121 <manual.html#121>`_
|
* `manual.html#121 <manual.html#121>`_
|
||||||
* `pegs.html#121 <pegs.html#121>`_
|
* `pegs.html#121 <pegs.html#121>`_
|
||||||
|
|
||||||
`newLine`:idx:
|
|
||||||
`pegs.html#122 <pegs.html#122>`_
|
|
||||||
|
|
||||||
`NewLines`:idx:
|
`NewLines`:idx:
|
||||||
`lexbase.html#102 <lexbase.html#102>`_
|
`lexbase.html#102 <lexbase.html#102>`_
|
||||||
|
|
||||||
|
|
@ -4246,12 +4245,12 @@ Index
|
||||||
`ord`:idx:
|
`ord`:idx:
|
||||||
`system.html#182 <system.html#182>`_
|
`system.html#182 <system.html#182>`_
|
||||||
|
|
||||||
`ordinal`:idx:
|
|
||||||
`tut1.html#114 <tut1.html#114>`_
|
|
||||||
|
|
||||||
`Ordinal`:idx:
|
`Ordinal`:idx:
|
||||||
`system.html#114 <system.html#114>`_
|
`system.html#114 <system.html#114>`_
|
||||||
|
|
||||||
|
`ordinal`:idx:
|
||||||
|
`tut1.html#114 <tut1.html#114>`_
|
||||||
|
|
||||||
`Ordinal types`:idx:
|
`Ordinal types`:idx:
|
||||||
`manual.html#142 <manual.html#142>`_
|
`manual.html#142 <manual.html#142>`_
|
||||||
|
|
||||||
|
|
@ -4313,12 +4312,12 @@ Index
|
||||||
`parseColor`:idx:
|
`parseColor`:idx:
|
||||||
`colors.html#249 <colors.html#249>`_
|
`colors.html#249 <colors.html#249>`_
|
||||||
|
|
||||||
`parseFloat`:idx:
|
|
||||||
`parseutils.html#111 <parseutils.html#111>`_
|
|
||||||
|
|
||||||
`ParseFloat`:idx:
|
`ParseFloat`:idx:
|
||||||
`strutils.html#144 <strutils.html#144>`_
|
`strutils.html#144 <strutils.html#144>`_
|
||||||
|
|
||||||
|
`parseFloat`:idx:
|
||||||
|
`parseutils.html#111 <parseutils.html#111>`_
|
||||||
|
|
||||||
`parseHex`:idx:
|
`parseHex`:idx:
|
||||||
`parseutils.html#101 <parseutils.html#101>`_
|
`parseutils.html#101 <parseutils.html#101>`_
|
||||||
|
|
||||||
|
|
@ -4332,17 +4331,17 @@ Index
|
||||||
`parseIdent`:idx:
|
`parseIdent`:idx:
|
||||||
`parseutils.html#103 <parseutils.html#103>`_
|
`parseutils.html#103 <parseutils.html#103>`_
|
||||||
|
|
||||||
`ParseInt`:idx:
|
|
||||||
`strutils.html#142 <strutils.html#142>`_
|
|
||||||
|
|
||||||
`parseInt`:idx:
|
`parseInt`:idx:
|
||||||
`parseutils.html#109 <parseutils.html#109>`_
|
`parseutils.html#109 <parseutils.html#109>`_
|
||||||
|
|
||||||
|
`ParseInt`:idx:
|
||||||
|
`strutils.html#142 <strutils.html#142>`_
|
||||||
|
|
||||||
`parseOct`:idx:
|
`parseOct`:idx:
|
||||||
`parseutils.html#102 <parseutils.html#102>`_
|
`parseutils.html#102 <parseutils.html#102>`_
|
||||||
|
|
||||||
`ParseOctInt`:idx:
|
`ParseOctInt`:idx:
|
||||||
`strutils.html#159 <strutils.html#159>`_
|
`strutils.html#158 <strutils.html#158>`_
|
||||||
|
|
||||||
`parsePeg`:idx:
|
`parsePeg`:idx:
|
||||||
`pegs.html#154 <pegs.html#154>`_
|
`pegs.html#154 <pegs.html#154>`_
|
||||||
|
|
@ -4644,8 +4643,7 @@ Index
|
||||||
`httpclient.html#109 <httpclient.html#109>`_
|
`httpclient.html#109 <httpclient.html#109>`_
|
||||||
|
|
||||||
`PostgreSQL`:idx:
|
`PostgreSQL`:idx:
|
||||||
* `db_postgres.html#101 <db_postgres.html#101>`_
|
`db_postgres.html#101 <db_postgres.html#101>`_
|
||||||
* `db_sqlite.html#101 <db_sqlite.html#101>`_
|
|
||||||
|
|
||||||
`pow`:idx:
|
`pow`:idx:
|
||||||
`math.html#132 <math.html#132>`_
|
`math.html#132 <math.html#132>`_
|
||||||
|
|
@ -4878,23 +4876,23 @@ Index
|
||||||
`streams.html#106 <streams.html#106>`_
|
`streams.html#106 <streams.html#106>`_
|
||||||
|
|
||||||
`readBuffer`:idx:
|
`readBuffer`:idx:
|
||||||
`system.html#530 <system.html#530>`_
|
`system.html#531 <system.html#531>`_
|
||||||
|
|
||||||
`ReadBytes`:idx:
|
`ReadBytes`:idx:
|
||||||
`system.html#528 <system.html#528>`_
|
`system.html#529 <system.html#529>`_
|
||||||
|
|
||||||
`readChar`:idx:
|
`readChar`:idx:
|
||||||
* `system.html#514 <system.html#514>`_
|
* `system.html#515 <system.html#515>`_
|
||||||
* `streams.html#105 <streams.html#105>`_
|
* `streams.html#105 <streams.html#105>`_
|
||||||
|
|
||||||
`ReadChars`:idx:
|
`ReadChars`:idx:
|
||||||
`system.html#529 <system.html#529>`_
|
`system.html#530 <system.html#530>`_
|
||||||
|
|
||||||
`readData`:idx:
|
`readData`:idx:
|
||||||
`cgi.html#109 <cgi.html#109>`_
|
`cgi.html#109 <cgi.html#109>`_
|
||||||
|
|
||||||
`readFile`:idx:
|
`readFile`:idx:
|
||||||
`system.html#516 <system.html#516>`_
|
`system.html#517 <system.html#517>`_
|
||||||
|
|
||||||
`readFloat32`:idx:
|
`readFloat32`:idx:
|
||||||
`streams.html#111 <streams.html#111>`_
|
`streams.html#111 <streams.html#111>`_
|
||||||
|
|
@ -4915,7 +4913,7 @@ Index
|
||||||
`streams.html#107 <streams.html#107>`_
|
`streams.html#107 <streams.html#107>`_
|
||||||
|
|
||||||
`readLine`:idx:
|
`readLine`:idx:
|
||||||
* `system.html#524 <system.html#524>`_
|
* `system.html#525 <system.html#525>`_
|
||||||
* `streams.html#114 <streams.html#114>`_
|
* `streams.html#114 <streams.html#114>`_
|
||||||
|
|
||||||
`readRow`:idx:
|
`readRow`:idx:
|
||||||
|
|
@ -5041,6 +5039,9 @@ Index
|
||||||
* `regexprs.html#117 <regexprs.html#117>`_
|
* `regexprs.html#117 <regexprs.html#117>`_
|
||||||
* `re.html#131 <re.html#131>`_
|
* `re.html#131 <re.html#131>`_
|
||||||
|
|
||||||
|
`reopen`:idx:
|
||||||
|
`system.html#511 <system.html#511>`_
|
||||||
|
|
||||||
`repeatChar`:idx:
|
`repeatChar`:idx:
|
||||||
`strutils.html#147 <strutils.html#147>`_
|
`strutils.html#147 <strutils.html#147>`_
|
||||||
|
|
||||||
|
|
@ -5256,7 +5257,7 @@ Index
|
||||||
`os.html#163 <os.html#163>`_
|
`os.html#163 <os.html#163>`_
|
||||||
|
|
||||||
`setFilePos`:idx:
|
`setFilePos`:idx:
|
||||||
`system.html#534 <system.html#534>`_
|
`system.html#535 <system.html#535>`_
|
||||||
|
|
||||||
`SET_FLAG`:idx:
|
`SET_FLAG`:idx:
|
||||||
`mysql.html#135 <mysql.html#135>`_
|
`mysql.html#135 <mysql.html#135>`_
|
||||||
|
|
@ -5378,6 +5379,9 @@ Index
|
||||||
* `db_postgres.html#106 <db_postgres.html#106>`_
|
* `db_postgres.html#106 <db_postgres.html#106>`_
|
||||||
* `db_sqlite.html#106 <db_sqlite.html#106>`_
|
* `db_sqlite.html#106 <db_sqlite.html#106>`_
|
||||||
|
|
||||||
|
`SQLite`:idx:
|
||||||
|
`db_sqlite.html#101 <db_sqlite.html#101>`_
|
||||||
|
|
||||||
`sqlite3_aggregate_context`:idx:
|
`sqlite3_aggregate_context`:idx:
|
||||||
`sqlite3.html#261 <sqlite3.html#261>`_
|
`sqlite3.html#261 <sqlite3.html#261>`_
|
||||||
|
|
||||||
|
|
@ -6401,7 +6405,7 @@ Index
|
||||||
`system.html#411 <system.html#411>`_
|
`system.html#411 <system.html#411>`_
|
||||||
|
|
||||||
`toBin`:idx:
|
`toBin`:idx:
|
||||||
`strutils.html#161 <strutils.html#161>`_
|
`strutils.html#160 <strutils.html#160>`_
|
||||||
|
|
||||||
`TObject`:idx:
|
`TObject`:idx:
|
||||||
`system.html#136 <system.html#136>`_
|
`system.html#136 <system.html#136>`_
|
||||||
|
|
@ -6421,7 +6425,7 @@ Index
|
||||||
* `unicode.html#111 <unicode.html#111>`_
|
* `unicode.html#111 <unicode.html#111>`_
|
||||||
|
|
||||||
`toOct`:idx:
|
`toOct`:idx:
|
||||||
`strutils.html#160 <strutils.html#160>`_
|
`strutils.html#159 <strutils.html#159>`_
|
||||||
|
|
||||||
`toOctal`:idx:
|
`toOctal`:idx:
|
||||||
`strutils.html#125 <strutils.html#125>`_
|
`strutils.html#125 <strutils.html#125>`_
|
||||||
|
|
@ -6722,10 +6726,10 @@ Index
|
||||||
`cgi.html#110 <cgi.html#110>`_
|
`cgi.html#110 <cgi.html#110>`_
|
||||||
|
|
||||||
`validEmailAddress`:idx:
|
`validEmailAddress`:idx:
|
||||||
`strutils.html#164 <strutils.html#164>`_
|
`strutils.html#163 <strutils.html#163>`_
|
||||||
|
|
||||||
`validIdentifier`:idx:
|
`validIdentifier`:idx:
|
||||||
`strutils.html#165 <strutils.html#165>`_
|
`strutils.html#164 <strutils.html#164>`_
|
||||||
|
|
||||||
`Var`:idx:
|
`Var`:idx:
|
||||||
`manual.html#187 <manual.html#187>`_
|
`manual.html#187 <manual.html#187>`_
|
||||||
|
|
@ -6788,32 +6792,32 @@ Index
|
||||||
`times.html#118 <times.html#118>`_
|
`times.html#118 <times.html#118>`_
|
||||||
|
|
||||||
`write`:idx:
|
`write`:idx:
|
||||||
* `system.html#517 <system.html#517>`_
|
|
||||||
* `system.html#518 <system.html#518>`_
|
* `system.html#518 <system.html#518>`_
|
||||||
* `system.html#519 <system.html#519>`_
|
* `system.html#519 <system.html#519>`_
|
||||||
* `system.html#520 <system.html#520>`_
|
* `system.html#520 <system.html#520>`_
|
||||||
* `system.html#521 <system.html#521>`_
|
* `system.html#521 <system.html#521>`_
|
||||||
* `system.html#522 <system.html#522>`_
|
* `system.html#522 <system.html#522>`_
|
||||||
* `system.html#523 <system.html#523>`_
|
* `system.html#523 <system.html#523>`_
|
||||||
|
* `system.html#524 <system.html#524>`_
|
||||||
* `streams.html#103 <streams.html#103>`_
|
* `streams.html#103 <streams.html#103>`_
|
||||||
* `streams.html#104 <streams.html#104>`_
|
* `streams.html#104 <streams.html#104>`_
|
||||||
* `ropes.html#118 <ropes.html#118>`_
|
* `ropes.html#118 <ropes.html#118>`_
|
||||||
|
|
||||||
`writeBuffer`:idx:
|
`writeBuffer`:idx:
|
||||||
`system.html#533 <system.html#533>`_
|
`system.html#534 <system.html#534>`_
|
||||||
|
|
||||||
`writeBytes`:idx:
|
`writeBytes`:idx:
|
||||||
`system.html#531 <system.html#531>`_
|
`system.html#532 <system.html#532>`_
|
||||||
|
|
||||||
`writeChars`:idx:
|
`writeChars`:idx:
|
||||||
`system.html#532 <system.html#532>`_
|
`system.html#533 <system.html#533>`_
|
||||||
|
|
||||||
`writeContentType`:idx:
|
`writeContentType`:idx:
|
||||||
`cgi.html#144 <cgi.html#144>`_
|
`cgi.html#144 <cgi.html#144>`_
|
||||||
|
|
||||||
`writeln`:idx:
|
`writeln`:idx:
|
||||||
* `system.html#525 <system.html#525>`_
|
|
||||||
* `system.html#526 <system.html#526>`_
|
* `system.html#526 <system.html#526>`_
|
||||||
|
* `system.html#527 <system.html#527>`_
|
||||||
|
|
||||||
`WriteStyled`:idx:
|
`WriteStyled`:idx:
|
||||||
`terminal.html#112 <terminal.html#112>`_
|
`terminal.html#112 <terminal.html#112>`_
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import re
|
||||||
|
|
||||||
for x in lines("myfile.txt"):
|
for x in lines("myfile.txt"):
|
||||||
if x =~ re"(\w+)=(.*)":
|
if x =~ re"(\w+)=(.*)":
|
||||||
echo "Key: ", matches[1],
|
echo "Key: ", matches[0],
|
||||||
" Value: ", matches[2]
|
" Value: ", matches[1]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@
|
||||||
|
|
||||||
|
|
||||||
## This module implements portable dialogs for Nimrod; the implementation
|
## This module implements portable dialogs for Nimrod; the implementation
|
||||||
## builds on the GTK interface. On Windows, native dialogs are shown if
|
## builds on the GTK interface. On Windows, native dialogs are shown instead.
|
||||||
## appropriate.
|
|
||||||
|
|
||||||
import
|
import
|
||||||
glib2, gtk2
|
glib2, gtk2
|
||||||
|
|
@ -174,7 +173,7 @@ proc ChooseFileToSave*(window: PWindow, root: string = ""): string =
|
||||||
var chooser = file_chooser_dialog_new("Save File", window,
|
var chooser = file_chooser_dialog_new("Save File", window,
|
||||||
FILE_CHOOSER_ACTION_SAVE,
|
FILE_CHOOSER_ACTION_SAVE,
|
||||||
STOCK_CANCEL, RESPONSE_CANCEL,
|
STOCK_CANCEL, RESPONSE_CANCEL,
|
||||||
STOCK_OPEN, RESPONSE_OK, nil)
|
STOCK_SAVE, RESPONSE_OK, nil)
|
||||||
if root.len > 0:
|
if root.len > 0:
|
||||||
discard set_current_folder(chooser, root)
|
discard set_current_folder(chooser, root)
|
||||||
set_do_overwrite_confirmation(chooser, true)
|
set_do_overwrite_confirmation(chooser, true)
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,13 @@ __TINYC__
|
||||||
|
|
||||||
#if !defined(__TINYC__)
|
#if !defined(__TINYC__)
|
||||||
# include <math.h>
|
# include <math.h>
|
||||||
|
#else
|
||||||
|
/*# define __GNUC__ 3
|
||||||
|
# define GCC_MAJOR 4
|
||||||
|
# define __GNUC_MINOR__ 4
|
||||||
|
# define __GNUC_PATCHLEVEL__ 5 */
|
||||||
|
|
||||||
|
# define __DECLSPEC_SUPPORTED 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* calling convention mess ----------------------------------------------- */
|
/* calling convention mess ----------------------------------------------- */
|
||||||
|
|
|
||||||
|
|
@ -953,8 +953,8 @@ proc parseCmdLine*(c: string): seq[string] =
|
||||||
## causing a literal double quotation mark (") to be placed in argv.
|
## causing a literal double quotation mark (") to be placed in argv.
|
||||||
##
|
##
|
||||||
## On Posix systems, it uses the following parsing rules:
|
## On Posix systems, it uses the following parsing rules:
|
||||||
## components are separated by
|
## Components are separated by whitespace unless the whitespace
|
||||||
## whitespace unless the whitespace occurs within ``"`` or ``'`` quotes.
|
## occurs within ``"`` or ``'`` quotes.
|
||||||
result = @[]
|
result = @[]
|
||||||
var i = 0
|
var i = 0
|
||||||
var a = ""
|
var a = ""
|
||||||
|
|
@ -963,6 +963,7 @@ proc parseCmdLine*(c: string): seq[string] =
|
||||||
while c[i] == ' ' or c[i] == '\t': inc(i)
|
while c[i] == ' ' or c[i] == '\t': inc(i)
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
# parse a single argument according to the above rules:
|
# parse a single argument according to the above rules:
|
||||||
|
if c[i] == '\0': break
|
||||||
var inQuote = false
|
var inQuote = false
|
||||||
while true:
|
while true:
|
||||||
case c[i]
|
case c[i]
|
||||||
|
|
@ -971,7 +972,7 @@ proc parseCmdLine*(c: string): seq[string] =
|
||||||
var j = i
|
var j = i
|
||||||
while c[j] == '\\': inc(j)
|
while c[j] == '\\': inc(j)
|
||||||
if c[j] == '"':
|
if c[j] == '"':
|
||||||
for k in 0..(j-i) div 2: a.add('\\')
|
for k in 1..(j-i) div 2: a.add('\\')
|
||||||
if (j-i) mod 2 == 0:
|
if (j-i) mod 2 == 0:
|
||||||
i = j
|
i = j
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,19 @@ type
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
type
|
type
|
||||||
TTime* = distinct int ## distinct type that represents a time
|
TTime* = distinct int ## distinct type that represents a time
|
||||||
|
|
||||||
|
Ttimeval {.importc: "struct timeval", header: "<sys/select.h>",
|
||||||
|
final, pure.} = object ## struct timeval
|
||||||
|
tv_sec: int ## Seconds.
|
||||||
|
tv_usec: int ## Microseconds.
|
||||||
|
|
||||||
|
# we cannot import posix.nim here, because posix.nim depends on times.nim.
|
||||||
|
# Ok, we could, but I don't want circular dependencies.
|
||||||
|
# And gettimeofday() is not defined in the posix module anyway. Sigh.
|
||||||
|
|
||||||
|
proc posix_gettimeofday(tp: var Ttimeval, unused: pointer = nil) {.
|
||||||
|
importc: "gettimeofday", header: "<sys/time.h>".}
|
||||||
|
|
||||||
elif defined(windows):
|
elif defined(windows):
|
||||||
when defined(vcc):
|
when defined(vcc):
|
||||||
# newest version of Visual C++ defines time_t to be of 64 bits
|
# newest version of Visual C++ defines time_t to be of 64 bits
|
||||||
|
|
@ -147,7 +160,7 @@ when not defined(ECMAScript):
|
||||||
PTimeInfo = ptr structTM
|
PTimeInfo = ptr structTM
|
||||||
PTime = ptr TTime
|
PTime = ptr TTime
|
||||||
|
|
||||||
TClock {.importc: "clock_t".} = range[low(int)..high(int)]
|
TClock {.importc: "clock_t".} = distinct int #range[low(int)..high(int)]
|
||||||
|
|
||||||
proc localtime(timer: PTime): PTimeInfo {.
|
proc localtime(timer: PTime): PTimeInfo {.
|
||||||
importc: "localtime", header: "<time.h>".}
|
importc: "localtime", header: "<time.h>".}
|
||||||
|
|
@ -197,9 +210,17 @@ when not defined(ECMAScript):
|
||||||
return toBiggestInt(difftime(a, b))
|
return toBiggestInt(difftime(a, b))
|
||||||
|
|
||||||
proc getStartMilsecs(): int =
|
proc getStartMilsecs(): int =
|
||||||
#echo "clocks per sec: ", clocksPerSec
|
#echo "clocks per sec: ", clocksPerSec, "clock: ", int(clock())
|
||||||
#return clock() div (clocksPerSec div 1000)
|
#return clock() div (clocksPerSec div 1000)
|
||||||
result = toInt(toFloat(clock()) / (toFloat(clocksPerSec) / 1000.0))
|
when defined(posix):
|
||||||
|
var a: Ttimeval
|
||||||
|
posix_gettimeofday(a)
|
||||||
|
result = a.tv_sec * 1000 + a.tv_usec
|
||||||
|
else:
|
||||||
|
result = int(clock()) div (clocksPerSec div 1000)
|
||||||
|
when false:
|
||||||
|
when defined(macosx):
|
||||||
|
result = toInt(toFloat(clock()) / (toFloat(clocksPerSec) / 1000.0))
|
||||||
|
|
||||||
proc getTime(): TTime = return timec(nil)
|
proc getTime(): TTime = return timec(nil)
|
||||||
proc getLocalTime(t: TTime): TTimeInfo =
|
proc getLocalTime(t: TTime): TTimeInfo =
|
||||||
|
|
|
||||||
|
|
@ -1176,3 +1176,5 @@ proc cmpRunesIgnoreCase*(a, b: string): int =
|
||||||
if result != 0: return
|
if result != 0: return
|
||||||
result = a.len - b.len
|
result = a.len - b.len
|
||||||
|
|
||||||
|
proc substringAt*(s, sub: string, start: int): int =
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -981,6 +981,9 @@ when not defined(NimrodVM):
|
||||||
proc getCurrentExceptionMsg*(): string {.exportc.}
|
proc getCurrentExceptionMsg*(): string {.exportc.}
|
||||||
## retrieves the error message that was attached to the current
|
## retrieves the error message that was attached to the current
|
||||||
## exception; if there is none, "" is returned.
|
## exception; if there is none, "" is returned.
|
||||||
|
|
||||||
|
proc getCurrentException*(): ref E_Base
|
||||||
|
## retrieves the current exception; if there is none, nil is returned.
|
||||||
|
|
||||||
# new constants:
|
# new constants:
|
||||||
const
|
const
|
||||||
|
|
@ -1390,6 +1393,13 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
##
|
##
|
||||||
## Default mode is readonly. Returns true iff the file could be opened.
|
## Default mode is readonly. Returns true iff the file could be opened.
|
||||||
|
|
||||||
|
proc reopen*(f: TFile, filename: string, mode: TFileMode = fmRead): bool
|
||||||
|
## reopens the file `f` with given `filename` and `mode`. This
|
||||||
|
## is often used to redirect the `stdin`, `stdout` or `stderr`
|
||||||
|
## file variables.
|
||||||
|
##
|
||||||
|
## Default mode is readonly. Returns true iff the file could be reopened.
|
||||||
|
|
||||||
proc CloseFile*(f: TFile) {.importc: "fclose", nodecl, deprecated.}
|
proc CloseFile*(f: TFile) {.importc: "fclose", nodecl, deprecated.}
|
||||||
## Closes the file.
|
## Closes the file.
|
||||||
## **Deprecated since version 0.8.0**: Use `close` instead.
|
## **Deprecated since version 0.8.0**: Use `close` instead.
|
||||||
|
|
@ -1554,6 +1564,7 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
else:
|
else:
|
||||||
result = n.sons[n.len]
|
result = n.sons[n.len]
|
||||||
|
|
||||||
|
include "system/systhread"
|
||||||
include "system/mm"
|
include "system/mm"
|
||||||
include "system/sysstr"
|
include "system/sysstr"
|
||||||
include "system/assign"
|
include "system/assign"
|
||||||
|
|
@ -1564,6 +1575,10 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
if excHandler == nil: return ""
|
if excHandler == nil: return ""
|
||||||
return $excHandler.exc.msg
|
return $excHandler.exc.msg
|
||||||
|
|
||||||
|
proc getCurrentException(): ref E_Base =
|
||||||
|
if excHandler != nil:
|
||||||
|
result = excHandler.exc
|
||||||
|
|
||||||
{.push stack_trace: off.}
|
{.push stack_trace: off.}
|
||||||
when defined(endb):
|
when defined(endb):
|
||||||
include "system/debugger"
|
include "system/debugger"
|
||||||
|
|
|
||||||
|
|
@ -376,10 +376,10 @@ proc freeBigChunk(a: var TAllocator, c: PBigChunk) =
|
||||||
|
|
||||||
proc splitChunk(a: var TAllocator, c: PBigChunk, size: int) =
|
proc splitChunk(a: var TAllocator, c: PBigChunk, size: int) =
|
||||||
var rest = cast[PBigChunk](cast[TAddress](c) +% size)
|
var rest = cast[PBigChunk](cast[TAddress](c) +% size)
|
||||||
if rest in a.freeChunksList:
|
assert(rest notin a.freeChunksList)
|
||||||
c_fprintf(c_stdout, "to add: %p\n", rest)
|
# c_fprintf(c_stdout, "to add: %p\n", rest)
|
||||||
writeFreeList(allocator)
|
# writeFreeList(allocator)
|
||||||
assert false
|
# assert false
|
||||||
rest.size = c.size - size
|
rest.size = c.size - size
|
||||||
rest.used = false
|
rest.used = false
|
||||||
rest.next = nil
|
rest.next = nil
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2009 Andreas Rumpf
|
# (c) Copyright 2010 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -478,6 +478,10 @@ proc gcMark(p: pointer) {.inline.} =
|
||||||
cell.refcount = cell.refcount +% rcIncrement
|
cell.refcount = cell.refcount +% rcIncrement
|
||||||
add(gch.decStack, cell)
|
add(gch.decStack, cell)
|
||||||
|
|
||||||
|
proc markThreadStacks(gch: var TGcHeap) =
|
||||||
|
when isMultiThreaded:
|
||||||
|
nil
|
||||||
|
|
||||||
# ----------------- stack management --------------------------------------
|
# ----------------- stack management --------------------------------------
|
||||||
# inspired from Smart Eiffel
|
# inspired from Smart Eiffel
|
||||||
|
|
||||||
|
|
@ -613,6 +617,7 @@ proc collectCT(gch: var TGcHeap) =
|
||||||
gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
|
gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
|
||||||
assert(gch.decStack.len == 0)
|
assert(gch.decStack.len == 0)
|
||||||
markStackAndRegisters(gch)
|
markStackAndRegisters(gch)
|
||||||
|
markThreadStacks(gch)
|
||||||
gch.stat.maxStackCells = max(gch.stat.maxStackCells, gch.decStack.len)
|
gch.stat.maxStackCells = max(gch.stat.maxStackCells, gch.decStack.len)
|
||||||
inc(gch.stat.stackScans)
|
inc(gch.stat.stackScans)
|
||||||
collectZCT(gch)
|
collectZCT(gch)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,9 @@ proc strlen(c: cstring): int {.importc: "strlen", nodecl.}
|
||||||
proc setvbuf(stream: TFile, buf: pointer, typ, size: cint): cint {.
|
proc setvbuf(stream: TFile, buf: pointer, typ, size: cint): cint {.
|
||||||
importc, nodecl.}
|
importc, nodecl.}
|
||||||
|
|
||||||
|
proc freopen(path, mode: cstring, stream: TFile): TFile {.importc: "freopen",
|
||||||
|
nodecl.}
|
||||||
|
|
||||||
proc write(f: TFile, c: cstring) = fputs(c, f)
|
proc write(f: TFile, c: cstring) = fputs(c, f)
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
@ -112,9 +115,7 @@ const
|
||||||
proc Open(f: var TFile, filename: string,
|
proc Open(f: var TFile, filename: string,
|
||||||
mode: TFileMode = fmRead,
|
mode: TFileMode = fmRead,
|
||||||
bufSize: int = -1): Bool =
|
bufSize: int = -1): Bool =
|
||||||
var
|
var p: pointer = fopen(filename, FormatOpen[mode])
|
||||||
p: pointer
|
|
||||||
p = fopen(filename, FormatOpen[mode])
|
|
||||||
result = (p != nil)
|
result = (p != nil)
|
||||||
f = cast[TFile](p)
|
f = cast[TFile](p)
|
||||||
if bufSize > 0:
|
if bufSize > 0:
|
||||||
|
|
@ -123,6 +124,10 @@ proc Open(f: var TFile, filename: string,
|
||||||
elif bufSize == 0:
|
elif bufSize == 0:
|
||||||
discard setvbuf(f, nil, IONBF, 0)
|
discard setvbuf(f, nil, IONBF, 0)
|
||||||
|
|
||||||
|
proc reopen(f: TFile, filename: string, mode: TFileMode = fmRead): bool =
|
||||||
|
var p: pointer = freopen(filename, FormatOpen[mode], f)
|
||||||
|
result = p != nil
|
||||||
|
|
||||||
proc fdopen(filehandle: TFileHandle, mode: cstring): TFile {.
|
proc fdopen(filehandle: TFileHandle, mode: cstring): TFile {.
|
||||||
importc: pccHack & "fdopen", header: "<stdio.h>".}
|
importc: pccHack & "fdopen", header: "<stdio.h>".}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -278,7 +278,7 @@ elif defined(macosx):
|
||||||
LibName = "libSDL-1.2.0.dylib"
|
LibName = "libSDL-1.2.0.dylib"
|
||||||
else:
|
else:
|
||||||
const
|
const
|
||||||
LibName = "libSDL.so"
|
LibName = "libSDL.so(|.1|.0)"
|
||||||
const
|
const
|
||||||
MAJOR_VERSION* = 1'i8
|
MAJOR_VERSION* = 1'i8
|
||||||
MINOR_VERSION* = 2'i8
|
MINOR_VERSION* = 2'i8
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ elif defined(macosx):
|
||||||
ttfLibName = "libSDL_ttf-2.0.0.dylib"
|
ttfLibName = "libSDL_ttf-2.0.0.dylib"
|
||||||
else:
|
else:
|
||||||
const
|
const
|
||||||
ttfLibName = "libSDL_ttf.so"
|
ttfLibName = "libSDL_ttf.so(|.1|.0)"
|
||||||
const
|
const
|
||||||
MAJOR_VERSION* = 2'i8
|
MAJOR_VERSION* = 2'i8
|
||||||
MINOR_VERSION* = 0'i8
|
MINOR_VERSION* = 0'i8
|
||||||
|
|
|
||||||
|
|
@ -417,23 +417,20 @@ proc renderRstToRst(d: PDoc, n: PRstNode): PRope =
|
||||||
# debugging, but most code is already debugged...
|
# debugging, but most code is already debugged...
|
||||||
const
|
const
|
||||||
lvlToChar: array[0..8, char] = ['!', '=', '-', '~', '`', '<', '*', '|', '+']
|
lvlToChar: array[0..8, char] = ['!', '=', '-', '~', '`', '<', '*', '|', '+']
|
||||||
var
|
|
||||||
L: int
|
|
||||||
ind: PRope
|
|
||||||
result = nil
|
result = nil
|
||||||
if n == nil: return
|
if n == nil: return
|
||||||
ind = toRope(repeatChar(d.indent))
|
var ind = toRope(repeatChar(d.indent))
|
||||||
case n.kind
|
case n.kind
|
||||||
of rnInner:
|
of rnInner:
|
||||||
result = renderRstSons(d, n)
|
result = renderRstSons(d, n)
|
||||||
of rnHeadline:
|
of rnHeadline:
|
||||||
result = renderRstSons(d, n)
|
result = renderRstSons(d, n)
|
||||||
L = ropeLen(result)
|
var L = ropeLen(result)
|
||||||
result = ropef("$n$1$2$n$1$3",
|
result = ropef("$n$1$2$n$1$3",
|
||||||
[ind, result, toRope(repeatChar(L, lvlToChar[n.level]))])
|
[ind, result, toRope(repeatChar(L, lvlToChar[n.level]))])
|
||||||
of rnOverline:
|
of rnOverline:
|
||||||
result = renderRstSons(d, n)
|
result = renderRstSons(d, n)
|
||||||
L = ropeLen(result)
|
var L = ropeLen(result)
|
||||||
result = ropef("$n$1$3$n$1$2$n$1$3",
|
result = ropef("$n$1$3$n$1$2$n$1$3",
|
||||||
[ind, result, toRope(repeatChar(L, lvlToChar[n.level]))])
|
[ind, result, toRope(repeatChar(L, lvlToChar[n.level]))])
|
||||||
of rnTransition:
|
of rnTransition:
|
||||||
|
|
@ -464,7 +461,7 @@ proc renderRstToRst(d: PDoc, n: PRstNode): PRope =
|
||||||
dec(d.indent, 2)
|
dec(d.indent, 2)
|
||||||
of rnField:
|
of rnField:
|
||||||
result = renderRstToRst(d, n.sons[0])
|
result = renderRstToRst(d, n.sons[0])
|
||||||
L = max(ropeLen(result) + 3, 30)
|
var L = max(ropeLen(result) + 3, 30)
|
||||||
inc(d.indent, L)
|
inc(d.indent, L)
|
||||||
result = ropef("$n$1:$2:$3$4", [ind, result, toRope(
|
result = ropef("$n$1:$2:$3$4", [ind, result, toRope(
|
||||||
repeatChar(L - ropeLen(result) - 2)), renderRstToRst(d, n.sons[1])])
|
repeatChar(L - ropeLen(result) - 2)), renderRstToRst(d, n.sons[1])])
|
||||||
|
|
|
||||||
|
|
@ -714,8 +714,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||||
var a = result
|
var a = result
|
||||||
result = newNodeIT(nkIntLit, n.info, n.typ)
|
result = newNodeIT(nkIntLit, n.info, n.typ)
|
||||||
case a.kind
|
case a.kind
|
||||||
of nkEmpty..nkNilLit:
|
of nkEmpty..nkNilLit: nil
|
||||||
nil
|
|
||||||
else: result.intVal = sonsLen(a)
|
else: result.intVal = sonsLen(a)
|
||||||
of mNChild:
|
of mNChild:
|
||||||
result = evalAux(c, n.sons[1], {efLValue})
|
result = evalAux(c, n.sons[1], {efLValue})
|
||||||
|
|
|
||||||
|
|
@ -1022,8 +1022,6 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
var s = qualifiedLookup(c, n.sons[0], false)
|
var s = qualifiedLookup(c, n.sons[0], false)
|
||||||
if s != nil and s.kind in {skProc, skMethod, skConverter, skIterator}:
|
if s != nil and s.kind in {skProc, skMethod, skConverter, skIterator}:
|
||||||
# type parameters: partial generic specialization
|
# type parameters: partial generic specialization
|
||||||
# XXX: too implement!
|
|
||||||
internalError(n.info, "explicit generic instantation not implemented")
|
|
||||||
result = partialSpecialization(c, n, s)
|
result = partialSpecialization(c, n, s)
|
||||||
else:
|
else:
|
||||||
result = semArrayAccess(c, n, flags)
|
result = semArrayAccess(c, n, flags)
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,28 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2009 Andreas Rumpf
|
# (c) Copyright 2010 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
# This module does the instantiation of generic procs and types.
|
# This module does the instantiation of generic procs and types.
|
||||||
|
|
||||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSym
|
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
|
info: TLineInfo): PSym
|
||||||
# generates an instantiated proc
|
# generates an instantiated proc
|
||||||
proc searchInstTypes(tab: TIdTable, key: PType): PType =
|
proc searchInstTypes(tab: TIdTable, key: PType): PType =
|
||||||
var
|
|
||||||
t: PType
|
|
||||||
match: bool
|
|
||||||
# returns nil if we need to declare this type
|
# returns nil if we need to declare this type
|
||||||
result = PType(IdTableGet(tab, key))
|
result = PType(IdTableGet(tab, key))
|
||||||
if (result == nil) and (tab.counter > 0):
|
if (result == nil) and (tab.counter > 0):
|
||||||
# we have to do a slow linear search because types may need
|
# we have to do a slow linear search because types may need
|
||||||
# to be compared by their structure:
|
# to be compared by their structure:
|
||||||
for h in countup(0, high(tab.data)):
|
for h in countup(0, high(tab.data)):
|
||||||
t = PType(tab.data[h].key)
|
var t = PType(tab.data[h].key)
|
||||||
if t != nil:
|
if t != nil:
|
||||||
if key.containerId == t.containerID:
|
if key.containerId == t.containerID:
|
||||||
match = true
|
var match = true
|
||||||
for j in countup(0, sonsLen(t) - 1):
|
for j in countup(0, sonsLen(t) - 1):
|
||||||
# XXX sameType is not really correct for nested generics?
|
# XXX sameType is not really correct for nested generics?
|
||||||
if not sameType(t.sons[j], key.sons[j]):
|
if not sameType(t.sons[j], key.sons[j]):
|
||||||
|
|
@ -39,20 +38,16 @@ proc containsGenericType(t: PType): bool =
|
||||||
result = iterOverType(t, containsGenericTypeIter, nil)
|
result = iterOverType(t, containsGenericTypeIter, nil)
|
||||||
|
|
||||||
proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
|
proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
|
||||||
var
|
|
||||||
s, q: PSym
|
|
||||||
t: PType
|
|
||||||
a: PNode
|
|
||||||
if (n.kind != nkGenericParams):
|
if (n.kind != nkGenericParams):
|
||||||
InternalError(n.info, "instantiateGenericParamList; no generic params")
|
InternalError(n.info, "instantiateGenericParamList; no generic params")
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if a.kind != nkSym:
|
if a.kind != nkSym:
|
||||||
InternalError(a.info, "instantiateGenericParamList; no symbol")
|
InternalError(a.info, "instantiateGenericParamList; no symbol")
|
||||||
q = a.sym
|
var q = a.sym
|
||||||
if not (q.typ.kind in {tyTypeDesc, tyGenericParam}): continue
|
if not (q.typ.kind in {tyTypeDesc, tyGenericParam}): continue
|
||||||
s = newSym(skType, q.name, getCurrOwner())
|
var s = newSym(skType, q.name, getCurrOwner())
|
||||||
t = PType(IdTableGet(pt, q.typ))
|
var t = PType(IdTableGet(pt, q.typ))
|
||||||
if t == nil: liMessage(a.info, errCannotInstantiateX, s.name.s)
|
if t == nil: liMessage(a.info, errCannotInstantiateX, s.name.s)
|
||||||
if (t.kind == tyGenericParam):
|
if (t.kind == tyGenericParam):
|
||||||
InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
|
InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
|
||||||
|
|
@ -60,27 +55,26 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
|
||||||
addDecl(c, s)
|
addDecl(c, s)
|
||||||
|
|
||||||
proc GenericCacheGet(c: PContext, genericSym, instSym: PSym): PSym =
|
proc GenericCacheGet(c: PContext, genericSym, instSym: PSym): PSym =
|
||||||
var a, b: PSym
|
|
||||||
result = nil
|
result = nil
|
||||||
for i in countup(0, sonsLen(c.generics) - 1):
|
for i in countup(0, sonsLen(c.generics) - 1):
|
||||||
if c.generics.sons[i].kind != nkExprEqExpr:
|
if c.generics.sons[i].kind != nkExprEqExpr:
|
||||||
InternalError(genericSym.info, "GenericCacheGet")
|
InternalError(genericSym.info, "GenericCacheGet")
|
||||||
a = c.generics.sons[i].sons[0].sym
|
var a = c.generics.sons[i].sons[0].sym
|
||||||
if genericSym.id == a.id:
|
if genericSym.id == a.id:
|
||||||
b = c.generics.sons[i].sons[1].sym
|
var b = c.generics.sons[i].sons[1].sym
|
||||||
if equalParams(b.typ.n, instSym.typ.n) == paramsEqual:
|
if equalParams(b.typ.n, instSym.typ.n) == paramsEqual:
|
||||||
#if gVerbosity > 0 then
|
#if gVerbosity > 0 then
|
||||||
# MessageOut('found in cache: ' + getProcHeader(instSym));
|
# MessageOut('found in cache: ' + getProcHeader(instSym));
|
||||||
return b
|
return b
|
||||||
|
|
||||||
proc GenericCacheAdd(c: PContext, genericSym, instSym: PSym) =
|
proc GenericCacheAdd(c: PContext, genericSym, instSym: PSym) =
|
||||||
var n: PNode
|
var n = newNode(nkExprEqExpr)
|
||||||
n = newNode(nkExprEqExpr)
|
|
||||||
addSon(n, newSymNode(genericSym))
|
addSon(n, newSymNode(genericSym))
|
||||||
addSon(n, newSymNode(instSym))
|
addSon(n, newSymNode(instSym))
|
||||||
addSon(c.generics, n)
|
addSon(c.generics, n)
|
||||||
|
|
||||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSym =
|
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
|
info: TLineInfo): PSym =
|
||||||
# generates an instantiated proc
|
# generates an instantiated proc
|
||||||
var
|
var
|
||||||
oldPrc, oldMod: PSym
|
oldPrc, oldMod: PSym
|
||||||
|
|
@ -89,8 +83,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSy
|
||||||
if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
|
if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
|
||||||
inc(c.InstCounter)
|
inc(c.InstCounter)
|
||||||
oldP = c.p # restore later
|
oldP = c.p # restore later
|
||||||
# NOTE: for access of private fields within generics from a different module
|
# NOTE: for access of private fields within generics from a different module
|
||||||
# and other identifiers we fake the current module temporarily!
|
# and other identifiers we fake the current module temporarily!
|
||||||
oldMod = c.module
|
oldMod = c.module
|
||||||
c.module = getModule(fn)
|
c.module = getModule(fn)
|
||||||
result = copySym(fn, false)
|
result = copySym(fn, false)
|
||||||
|
|
@ -151,8 +145,6 @@ type
|
||||||
proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType
|
proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType
|
||||||
proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
|
proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
|
||||||
proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
||||||
var length: int
|
|
||||||
result = nil
|
|
||||||
if n != nil:
|
if n != nil:
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
result.typ = ReplaceTypeVarsT(cl, n.typ)
|
result.typ = ReplaceTypeVarsT(cl, n.typ)
|
||||||
|
|
@ -162,7 +154,7 @@ proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
||||||
of nkSym:
|
of nkSym:
|
||||||
result.sym = ReplaceTypeVarsS(cl, n.sym)
|
result.sym = ReplaceTypeVarsS(cl, n.sym)
|
||||||
else:
|
else:
|
||||||
length = sonsLen(n)
|
var length = sonsLen(n)
|
||||||
if length > 0:
|
if length > 0:
|
||||||
newSons(result, length)
|
newSons(result, length)
|
||||||
for i in countup(0, length - 1):
|
for i in countup(0, length - 1):
|
||||||
|
|
@ -172,7 +164,7 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
|
||||||
if s == nil:
|
if s == nil:
|
||||||
return nil
|
return nil
|
||||||
result = PSym(idTableGet(cl.symMap, s))
|
result = PSym(idTableGet(cl.symMap, s))
|
||||||
if (result == nil):
|
if result == nil:
|
||||||
result = copySym(s, false)
|
result = copySym(s, false)
|
||||||
incl(result.flags, sfFromGeneric)
|
incl(result.flags, sfFromGeneric)
|
||||||
idTablePut(cl.symMap, s, result)
|
idTablePut(cl.symMap, s, result)
|
||||||
|
|
@ -229,8 +221,9 @@ proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType =
|
||||||
result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
|
result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
|
||||||
result.n = ReplaceTypeVarsN(cl, result.n)
|
result.n = ReplaceTypeVarsN(cl, result.n)
|
||||||
if result.Kind in GenericTypes:
|
if result.Kind in GenericTypes:
|
||||||
liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName)) #writeln(output, ropeToStr(Typetoyaml(result)));
|
liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
|
||||||
#checkConstructedType(cl.info, result);
|
#writeln(output, ropeToStr(Typetoyaml(result)))
|
||||||
|
#checkConstructedType(cl.info, result)
|
||||||
|
|
||||||
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
|
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
|
||||||
var cl: TReplTypeVars
|
var cl: TReplTypeVars
|
||||||
|
|
@ -240,7 +233,8 @@ proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
|
||||||
cl.c = c
|
cl.c = c
|
||||||
result = ReplaceTypeVarsT(cl, header)
|
result = ReplaceTypeVarsT(cl, header)
|
||||||
|
|
||||||
proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode, t: PType): PType =
|
proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode,
|
||||||
|
t: PType): PType =
|
||||||
var cl: TReplTypeVars
|
var cl: TReplTypeVars
|
||||||
InitIdTable(cl.symMap)
|
InitIdTable(cl.symMap)
|
||||||
copyIdTable(cl.typeMap, pt)
|
copyIdTable(cl.typeMap, pt)
|
||||||
|
|
@ -251,4 +245,9 @@ proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode, t: PType): PTyp
|
||||||
popInfoContext()
|
popInfoContext()
|
||||||
|
|
||||||
proc partialSpecialization(c: PContext, n: PNode, s: PSym): PNode =
|
proc partialSpecialization(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
|
for i in 1..sonsLen(n)-1:
|
||||||
|
n.sons[i].typ = semTypeNode(c, n.sons[i], nil)
|
||||||
|
# we cannot check for the proper number of type parameters because in
|
||||||
|
# `f[a,b](x, y)` `f` is not resolved yet properly.
|
||||||
|
# XXX: BUG this should be checked somehow!
|
||||||
result = n
|
result = n
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
# this module does the semantic checking of statements
|
# this module does the semantic checking of statements
|
||||||
|
|
||||||
proc semExprNoType(c: PContext, n: PNode): PNode =
|
proc semExprNoType(c: PContext, n: PNode): PNode =
|
||||||
|
|
@ -267,14 +268,13 @@ proc SemReturn(c: PContext, n: PNode): PNode =
|
||||||
liMessage(n.info, errCannotReturnExpr)
|
liMessage(n.info, errCannotReturnExpr)
|
||||||
|
|
||||||
proc SemYield(c: PContext, n: PNode): PNode =
|
proc SemYield(c: PContext, n: PNode): PNode =
|
||||||
var restype: PType
|
|
||||||
result = n
|
result = n
|
||||||
checkSonsLen(n, 1)
|
checkSonsLen(n, 1)
|
||||||
if (c.p.owner == nil) or (c.p.owner.kind != skIterator):
|
if (c.p.owner == nil) or (c.p.owner.kind != skIterator):
|
||||||
liMessage(n.info, errYieldNotAllowedHere)
|
liMessage(n.info, errYieldNotAllowedHere)
|
||||||
if (n.sons[0] != nil):
|
if (n.sons[0] != nil):
|
||||||
n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
|
n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
|
||||||
restype = c.p.owner.typ.sons[0]
|
var restype = c.p.owner.typ.sons[0]
|
||||||
if (restype != nil):
|
if (restype != nil):
|
||||||
n.sons[0] = fitNode(c, restype, n.sons[0])
|
n.sons[0] = fitNode(c, restype, n.sons[0])
|
||||||
if (n.sons[0].typ == nil): InternalError(n.info, "semYield")
|
if (n.sons[0].typ == nil): InternalError(n.info, "semYield")
|
||||||
|
|
@ -477,6 +477,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||||
s = newSymS(skType, a.sons[j], c)
|
s = newSymS(skType, a.sons[j], c)
|
||||||
s.typ = newTypeS(tyGenericParam, c)
|
s.typ = newTypeS(tyGenericParam, c)
|
||||||
else:
|
else:
|
||||||
|
# not a type param, but an expression
|
||||||
s = newSymS(skGenericParam, a.sons[j], c)
|
s = newSymS(skGenericParam, a.sons[j], c)
|
||||||
s.typ = typ
|
s.typ = typ
|
||||||
s.ast = def
|
s.ast = def
|
||||||
|
|
|
||||||
135
rod/semtypes.nim
135
rod/semtypes.nim
|
|
@ -6,6 +6,7 @@
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
# this module does the semantic checking of type declarations
|
# this module does the semantic checking of type declarations
|
||||||
|
|
||||||
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
|
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
|
||||||
|
|
@ -63,10 +64,9 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||||
inc(counter)
|
inc(counter)
|
||||||
|
|
||||||
proc semSet(c: PContext, n: PNode, prev: PType): PType =
|
proc semSet(c: PContext, n: PNode, prev: PType): PType =
|
||||||
var base: PType
|
|
||||||
result = newOrPrevType(tySet, prev, c)
|
result = newOrPrevType(tySet, prev, c)
|
||||||
if sonsLen(n) == 2:
|
if sonsLen(n) == 2:
|
||||||
base = semTypeNode(c, n.sons[1], nil)
|
var base = semTypeNode(c, n.sons[1], nil)
|
||||||
addSon(result, base)
|
addSon(result, base)
|
||||||
if base.kind == tyGenericInst: base = lastSon(base)
|
if base.kind == tyGenericInst: base = lastSon(base)
|
||||||
if base.kind != tyGenericParam:
|
if base.kind != tyGenericParam:
|
||||||
|
|
@ -77,29 +77,26 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
|
||||||
|
|
||||||
proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
|
proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
|
||||||
prev: PType): PType =
|
prev: PType): PType =
|
||||||
var base: PType
|
|
||||||
result = newOrPrevType(kind, prev, c)
|
result = newOrPrevType(kind, prev, c)
|
||||||
if sonsLen(n) == 2:
|
if sonsLen(n) == 2:
|
||||||
base = semTypeNode(c, n.sons[1], nil)
|
var base = semTypeNode(c, n.sons[1], nil)
|
||||||
addSon(result, base)
|
addSon(result, base)
|
||||||
else:
|
else:
|
||||||
liMessage(n.info, errXExpectsOneTypeParam, kindStr)
|
liMessage(n.info, errXExpectsOneTypeParam, kindStr)
|
||||||
|
|
||||||
proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
|
proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
|
||||||
prev: PType): PType =
|
prev: PType): PType =
|
||||||
var base: PType
|
|
||||||
result = newOrPrevType(kind, prev, c)
|
result = newOrPrevType(kind, prev, c)
|
||||||
if sonsLen(n) == 1:
|
if sonsLen(n) == 1:
|
||||||
base = semTypeNode(c, n.sons[0], nil)
|
var base = semTypeNode(c, n.sons[0], nil)
|
||||||
addSon(result, base)
|
addSon(result, base)
|
||||||
else:
|
else:
|
||||||
liMessage(n.info, errXExpectsOneTypeParam, kindStr)
|
liMessage(n.info, errXExpectsOneTypeParam, kindStr)
|
||||||
|
|
||||||
proc semVarType(c: PContext, n: PNode, prev: PType): PType =
|
proc semVarType(c: PContext, n: PNode, prev: PType): PType =
|
||||||
var base: PType
|
|
||||||
result = newOrPrevType(tyVar, prev, c)
|
result = newOrPrevType(tyVar, prev, c)
|
||||||
if sonsLen(n) == 1:
|
if sonsLen(n) == 1:
|
||||||
base = semTypeNode(c, n.sons[0], nil)
|
var base = semTypeNode(c, n.sons[0], nil)
|
||||||
if base.kind == tyVar: liMessage(n.info, errVarVarTypeNotAllowed)
|
if base.kind == tyVar: liMessage(n.info, errVarVarTypeNotAllowed)
|
||||||
addSon(result, base)
|
addSon(result, base)
|
||||||
else:
|
else:
|
||||||
|
|
@ -111,15 +108,14 @@ proc semDistinct(c: PContext, n: PNode, prev: PType): PType =
|
||||||
else: liMessage(n.info, errXExpectsOneTypeParam, "distinct")
|
else: liMessage(n.info, errXExpectsOneTypeParam, "distinct")
|
||||||
|
|
||||||
proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
|
proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
|
||||||
var a, b: PNode
|
|
||||||
if (n.kind != nkRange): InternalError(n.info, "semRangeAux")
|
if (n.kind != nkRange): InternalError(n.info, "semRangeAux")
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
result = newOrPrevType(tyRange, prev, c)
|
result = newOrPrevType(tyRange, prev, c)
|
||||||
result.n = newNodeI(nkRange, n.info)
|
result.n = newNodeI(nkRange, n.info)
|
||||||
if (n.sons[0] == nil) or (n.sons[1] == nil):
|
if (n.sons[0] == nil) or (n.sons[1] == nil):
|
||||||
liMessage(n.Info, errRangeIsEmpty)
|
liMessage(n.Info, errRangeIsEmpty)
|
||||||
a = semConstExpr(c, n.sons[0])
|
var a = semConstExpr(c, n.sons[0])
|
||||||
b = semConstExpr(c, n.sons[1])
|
var b = semConstExpr(c, n.sons[1])
|
||||||
if not sameType(a.typ, b.typ): liMessage(n.info, errPureTypeMismatch)
|
if not sameType(a.typ, b.typ): liMessage(n.info, errPureTypeMismatch)
|
||||||
if not (a.typ.kind in
|
if not (a.typ.kind in
|
||||||
{tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}):
|
{tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}):
|
||||||
|
|
@ -159,10 +155,9 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||||
liMessage(n.info, errArrayExpectsTwoTypeParams)
|
liMessage(n.info, errArrayExpectsTwoTypeParams)
|
||||||
|
|
||||||
proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
|
proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
|
||||||
var base: PType
|
|
||||||
result = newOrPrevType(tyOrdinal, prev, c)
|
result = newOrPrevType(tyOrdinal, prev, c)
|
||||||
if sonsLen(n) == 2:
|
if sonsLen(n) == 2:
|
||||||
base = semTypeNode(c, n.sons[1], nil)
|
var base = semTypeNode(c, n.sons[1], nil)
|
||||||
if base.kind != tyGenericParam:
|
if base.kind != tyGenericParam:
|
||||||
if not isOrdinalType(base):
|
if not isOrdinalType(base):
|
||||||
liMessage(n.sons[1].info, errOrdinalTypeExpected)
|
liMessage(n.sons[1].info, errOrdinalTypeExpected)
|
||||||
|
|
@ -231,7 +226,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
|
||||||
allowed: TSymFlags): PSym =
|
allowed: TSymFlags): PSym =
|
||||||
# identifier with visibility
|
# identifier with visibility
|
||||||
if n.kind == nkPostfix:
|
if n.kind == nkPostfix:
|
||||||
if (sonsLen(n) == 2) and (n.sons[0].kind == nkIdent):
|
if sonsLen(n) == 2 and n.sons[0].kind == nkIdent:
|
||||||
result = newSymS(kind, n.sons[1], c)
|
result = newSymS(kind, n.sons[1], c)
|
||||||
var v = n.sons[0].ident
|
var v = n.sons[0].ident
|
||||||
if (sfStar in allowed) and (v.id == ord(wStar)):
|
if (sfStar in allowed) and (v.id == ord(wStar)):
|
||||||
|
|
@ -426,7 +421,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
base: PType
|
base: PType
|
||||||
pos: int
|
pos: int
|
||||||
IntSetInit(check)
|
IntSetInit(check)
|
||||||
pos = 0 # n.sons[0] contains the pragmas (if any). We process these later...
|
pos = 0 # n.sons[0] contains the pragmas (if any). We process these later...
|
||||||
checkSonsLen(n, 3)
|
checkSonsLen(n, 3)
|
||||||
if n.sons[1] != nil:
|
if n.sons[1] != nil:
|
||||||
base = semTypeNode(c, n.sons[1].sons[0], nil)
|
base = semTypeNode(c, n.sons[1].sons[0], nil)
|
||||||
|
|
@ -444,28 +439,30 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
|
|
||||||
proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode,
|
proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode,
|
||||||
cl: var TIntSet): PType =
|
cl: var TIntSet): PType =
|
||||||
var
|
|
||||||
L: int
|
|
||||||
s: PSym
|
|
||||||
result = t
|
result = t
|
||||||
if (t == nil): return
|
if t == nil: return
|
||||||
if IntSetContainsOrIncl(cl, t.id): return
|
if IntSetContainsOrIncl(cl, t.id): return
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyGenericBody:
|
of tyGenericBody:
|
||||||
|
#debug(t)
|
||||||
result = newTypeS(tyGenericInvokation, c)
|
result = newTypeS(tyGenericInvokation, c)
|
||||||
addSon(result, t)
|
addSon(result, t)
|
||||||
for i in countup(0, sonsLen(t) - 2):
|
for i in countup(0, sonsLen(t) - 2):
|
||||||
if t.sons[i].kind != tyGenericParam:
|
if t.sons[i].kind != tyGenericParam:
|
||||||
InternalError("addTypeVarsOfGenericBody")
|
InternalError("addTypeVarsOfGenericBody")
|
||||||
s = copySym(t.sons[i].sym)
|
# do not declare ``TKey`` twice:
|
||||||
|
#if not IntSetContainsOrIncl(cl, t.sons[i].sym.ident.id):
|
||||||
|
var s = copySym(t.sons[i].sym)
|
||||||
s.position = sonsLen(genericParams)
|
s.position = sonsLen(genericParams)
|
||||||
addDecl(c, s)
|
addDecl(c, s)
|
||||||
addSon(genericParams, newSymNode(s))
|
addSon(genericParams, newSymNode(s))
|
||||||
addSon(result, t.sons[i])
|
addSon(result, t.sons[i])
|
||||||
of tyGenericInst:
|
of tyGenericInst:
|
||||||
L = sonsLen(t) - 1
|
#debug(t)
|
||||||
|
var L = sonsLen(t) - 1
|
||||||
t.sons[L] = addTypeVarsOfGenericBody(c, t.sons[L], genericParams, cl)
|
t.sons[L] = addTypeVarsOfGenericBody(c, t.sons[L], genericParams, cl)
|
||||||
of tyGenericInvokation:
|
of tyGenericInvokation:
|
||||||
|
#debug(t)
|
||||||
for i in countup(1, sonsLen(t) - 1):
|
for i in countup(1, sonsLen(t) - 1):
|
||||||
t.sons[i] = addTypeVarsOfGenericBody(c, t.sons[i], genericParams, cl)
|
t.sons[i] = addTypeVarsOfGenericBody(c, t.sons[i], genericParams, cl)
|
||||||
else:
|
else:
|
||||||
|
|
@ -476,13 +473,12 @@ proc paramType(c: PContext, n, genericParams: PNode, cl: var TIntSet): PType =
|
||||||
result = semTypeNode(c, n, nil)
|
result = semTypeNode(c, n, nil)
|
||||||
if (genericParams != nil) and (sonsLen(genericParams) == 0):
|
if (genericParams != nil) and (sonsLen(genericParams) == 0):
|
||||||
result = addTypeVarsOfGenericBody(c, result, genericParams, cl)
|
result = addTypeVarsOfGenericBody(c, result, genericParams, cl)
|
||||||
|
#if result.kind == tyGenericInvokation: debug(result)
|
||||||
|
|
||||||
proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
|
proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
|
||||||
var
|
var
|
||||||
length, counter: int
|
def, res: PNode
|
||||||
a, def, res: PNode
|
|
||||||
typ: PType
|
typ: PType
|
||||||
arg: PSym
|
|
||||||
check, cl: TIntSet
|
check, cl: TIntSet
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
result = newOrPrevType(tyProc, prev, c)
|
result = newOrPrevType(tyProc, prev, c)
|
||||||
|
|
@ -491,27 +487,29 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
|
||||||
if (genericParams != nil) and (sonsLen(genericParams) == 0): IntSetInit(cl)
|
if (genericParams != nil) and (sonsLen(genericParams) == 0): IntSetInit(cl)
|
||||||
if n.sons[0] == nil:
|
if n.sons[0] == nil:
|
||||||
addSon(result, nil) # return type
|
addSon(result, nil) # return type
|
||||||
addSon(result.n, newNodeI(nkType, n.info)) # BUGFIX: nkType must exist!
|
addSon(result.n, newNodeI(nkType, n.info))
|
||||||
# XXX but it does not, if n.sons[paramsPos] == nil?
|
# BUGFIX: nkType must exist!
|
||||||
|
# XXX but it does not, if n.sons[paramsPos] == nil?
|
||||||
else:
|
else:
|
||||||
addSon(result, nil)
|
addSon(result, nil)
|
||||||
res = newNodeI(nkType, n.info)
|
res = newNodeI(nkType, n.info)
|
||||||
addSon(result.n, res)
|
addSon(result.n, res)
|
||||||
IntSetInit(check)
|
IntSetInit(check)
|
||||||
counter = 0
|
var counter = 0
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if (a.kind != nkIdentDefs): IllFormedAst(a)
|
if a.kind != nkIdentDefs: IllFormedAst(a)
|
||||||
checkMinSonsLen(a, 3)
|
checkMinSonsLen(a, 3)
|
||||||
length = sonsLen(a)
|
var length = sonsLen(a)
|
||||||
if a.sons[length - 2] != nil:
|
if a.sons[length - 2] != nil:
|
||||||
typ = paramType(c, a.sons[length - 2], genericParams, cl)
|
typ = paramType(c, a.sons[length - 2], genericParams, cl)
|
||||||
else:
|
else:
|
||||||
typ = nil
|
typ = nil
|
||||||
if a.sons[length - 1] != nil:
|
if a.sons[length - 1] != nil:
|
||||||
def = semExprWithType(c, a.sons[length - 1]) # check type compability between def.typ and typ:
|
def = semExprWithType(c, a.sons[length - 1])
|
||||||
if (typ != nil):
|
# check type compability between def.typ and typ:
|
||||||
if (cmpTypes(typ, def.typ) < isConvertible):
|
if typ != nil:
|
||||||
|
if cmpTypes(typ, def.typ) < isConvertible:
|
||||||
typeMismatch(a.sons[length - 1], typ, def.typ)
|
typeMismatch(a.sons[length - 1], typ, def.typ)
|
||||||
def = fitNode(c, typ, def)
|
def = fitNode(c, typ, def)
|
||||||
else:
|
else:
|
||||||
|
|
@ -519,7 +517,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
|
||||||
else:
|
else:
|
||||||
def = nil
|
def = nil
|
||||||
for j in countup(0, length - 3):
|
for j in countup(0, length - 3):
|
||||||
arg = newSymS(skParam, a.sons[j], c)
|
var arg = newSymS(skParam, a.sons[j], c)
|
||||||
arg.typ = typ
|
arg.typ = typ
|
||||||
arg.position = counter
|
arg.position = counter
|
||||||
inc(counter)
|
inc(counter)
|
||||||
|
|
@ -600,21 +598,16 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
markUsed(n, n.sym)
|
markUsed(n, n.sym)
|
||||||
else:
|
else:
|
||||||
liMessage(n.info, errTypeExpected)
|
liMessage(n.info, errTypeExpected)
|
||||||
of nkObjectTy:
|
of nkObjectTy: result = semObjectNode(c, n, prev)
|
||||||
result = semObjectNode(c, n, prev)
|
of nkTupleTy: result = semTuple(c, n, prev)
|
||||||
of nkTupleTy:
|
of nkRefTy: result = semAnyRef(c, n, tyRef, "ref", prev)
|
||||||
result = semTuple(c, n, prev)
|
of nkPtrTy: result = semAnyRef(c, n, tyPtr, "ptr", prev)
|
||||||
of nkRefTy:
|
of nkVarTy: result = semVarType(c, n, prev)
|
||||||
result = semAnyRef(c, n, tyRef, "ref", prev)
|
of nkDistinctTy: result = semDistinct(c, n, prev)
|
||||||
of nkPtrTy:
|
|
||||||
result = semAnyRef(c, n, tyPtr, "ptr", prev)
|
|
||||||
of nkVarTy:
|
|
||||||
result = semVarType(c, n, prev)
|
|
||||||
of nkDistinctTy:
|
|
||||||
result = semDistinct(c, n, prev)
|
|
||||||
of nkProcTy:
|
of nkProcTy:
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
result = semProcTypeNode(c, n.sons[0], nil, prev) # dummy symbol for `pragma`:
|
result = semProcTypeNode(c, n.sons[0], nil, prev)
|
||||||
|
# dummy symbol for `pragma`:
|
||||||
s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
|
s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
|
||||||
s.typ = result
|
s.typ = result
|
||||||
pragma(c, s, n.sons[1], procTypePragmas)
|
pragma(c, s, n.sons[1], procTypePragmas)
|
||||||
|
|
@ -636,49 +629,33 @@ proc setMagicType(m: PSym, kind: TTypeKind, size: int) =
|
||||||
|
|
||||||
proc processMagicType(c: PContext, m: PSym) =
|
proc processMagicType(c: PContext, m: PSym) =
|
||||||
case m.magic #registerSysType(m.typ);
|
case m.magic #registerSysType(m.typ);
|
||||||
of mInt:
|
of mInt: setMagicType(m, tyInt, intSize)
|
||||||
setMagicType(m, tyInt, intSize)
|
of mInt8: setMagicType(m, tyInt8, 1)
|
||||||
of mInt8:
|
of mInt16: setMagicType(m, tyInt16, 2)
|
||||||
setMagicType(m, tyInt8, 1)
|
of mInt32: setMagicType(m, tyInt32, 4)
|
||||||
of mInt16:
|
of mInt64: setMagicType(m, tyInt64, 8)
|
||||||
setMagicType(m, tyInt16, 2)
|
of mFloat: setMagicType(m, tyFloat, floatSize)
|
||||||
of mInt32:
|
of mFloat32: setMagicType(m, tyFloat32, 4)
|
||||||
setMagicType(m, tyInt32, 4)
|
of mFloat64: setMagicType(m, tyFloat64, 8)
|
||||||
of mInt64:
|
of mBool: setMagicType(m, tyBool, 1)
|
||||||
setMagicType(m, tyInt64, 8)
|
of mChar: setMagicType(m, tyChar, 1)
|
||||||
of mFloat:
|
|
||||||
setMagicType(m, tyFloat, floatSize)
|
|
||||||
of mFloat32:
|
|
||||||
setMagicType(m, tyFloat32, 4)
|
|
||||||
of mFloat64:
|
|
||||||
setMagicType(m, tyFloat64, 8)
|
|
||||||
of mBool:
|
|
||||||
setMagicType(m, tyBool, 1)
|
|
||||||
of mChar:
|
|
||||||
setMagicType(m, tyChar, 1)
|
|
||||||
of mString:
|
of mString:
|
||||||
setMagicType(m, tyString, ptrSize)
|
setMagicType(m, tyString, ptrSize)
|
||||||
addSon(m.typ, getSysType(tyChar))
|
addSon(m.typ, getSysType(tyChar))
|
||||||
of mCstring:
|
of mCstring:
|
||||||
setMagicType(m, tyCString, ptrSize)
|
setMagicType(m, tyCString, ptrSize)
|
||||||
addSon(m.typ, getSysType(tyChar))
|
addSon(m.typ, getSysType(tyChar))
|
||||||
of mPointer:
|
of mPointer: setMagicType(m, tyPointer, ptrSize)
|
||||||
setMagicType(m, tyPointer, ptrSize)
|
|
||||||
of mEmptySet:
|
of mEmptySet:
|
||||||
setMagicType(m, tySet, 1)
|
setMagicType(m, tySet, 1)
|
||||||
addSon(m.typ, newTypeS(tyEmpty, c))
|
addSon(m.typ, newTypeS(tyEmpty, c))
|
||||||
of mIntSetBaseType:
|
of mIntSetBaseType:
|
||||||
setMagicType(m, tyRange, intSize) #intSetBaseType := m.typ;
|
setMagicType(m, tyRange, intSize) #intSetBaseType := m.typ;
|
||||||
return
|
return
|
||||||
of mNil:
|
of mNil: setMagicType(m, tyNil, ptrSize)
|
||||||
setMagicType(m, tyNil, ptrSize)
|
of mExpr: setMagicType(m, tyExpr, 0)
|
||||||
of mExpr:
|
of mStmt: setMagicType(m, tyStmt, 0)
|
||||||
setMagicType(m, tyExpr, 0)
|
of mTypeDesc: setMagicType(m, tyTypeDesc, 0)
|
||||||
of mStmt:
|
of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: return
|
||||||
setMagicType(m, tyStmt, 0)
|
|
||||||
of mTypeDesc:
|
|
||||||
setMagicType(m, tyTypeDesc, 0)
|
|
||||||
of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal:
|
|
||||||
return
|
|
||||||
else: liMessage(m.info, errTypeExpected)
|
else: liMessage(m.info, errTypeExpected)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ type
|
||||||
TTypeRelation = enum # order is important!
|
TTypeRelation = enum # order is important!
|
||||||
isNone, isConvertible, isIntConv, isSubtype, isGeneric, isEqual
|
isNone, isConvertible, isIntConv, isSubtype, isGeneric, isEqual
|
||||||
|
|
||||||
proc initCandidate(c: var TCandidate, callee: PType) =
|
proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} =
|
||||||
c.exactMatches = 0
|
c.exactMatches = 0
|
||||||
c.subtypeMatches = 0
|
c.subtypeMatches = 0
|
||||||
c.convMatches = 0
|
c.convMatches = 0
|
||||||
|
|
@ -38,11 +38,25 @@ proc initCandidate(c: var TCandidate, callee: PType) =
|
||||||
c.genericMatches = 0
|
c.genericMatches = 0
|
||||||
c.state = csEmpty
|
c.state = csEmpty
|
||||||
c.callee = callee
|
c.callee = callee
|
||||||
c.calleeSym = nil
|
|
||||||
c.call = nil
|
c.call = nil
|
||||||
c.baseTypeMatch = false
|
c.baseTypeMatch = false
|
||||||
initIdTable(c.bindings) #assert(c.callee <> nil);
|
|
||||||
|
proc initCandidate(c: var TCandidate, callee: PType) =
|
||||||
|
initCandidateAux(c, callee)
|
||||||
|
c.calleeSym = nil
|
||||||
|
initIdTable(c.bindings)
|
||||||
|
|
||||||
|
proc initCandidate(c: var TCandidate, callee: PSym, binding: PNode) =
|
||||||
|
initCandidateAux(c, callee.typ)
|
||||||
|
c.calleeSym = callee
|
||||||
|
initIdTable(c.bindings)
|
||||||
|
if binding != nil:
|
||||||
|
var typeParams = callee.ast[genericParamsPos]
|
||||||
|
for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
|
||||||
|
var formalTypeParam = typeParams.sons[i-1].typ
|
||||||
|
#debug(formalTypeParam)
|
||||||
|
IdTablePut(c.bindings, formalTypeParam, binding[i].typ)
|
||||||
|
|
||||||
proc copyCandidate(a: var TCandidate, b: TCandidate) =
|
proc copyCandidate(a: var TCandidate, b: TCandidate) =
|
||||||
a.exactMatches = b.exactMatches
|
a.exactMatches = b.exactMatches
|
||||||
a.subtypeMatches = b.subtypeMatches
|
a.subtypeMatches = b.subtypeMatches
|
||||||
|
|
@ -326,7 +340,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
case a.kind
|
case a.kind
|
||||||
of tyPointer: result = isEqual
|
of tyPointer: result = isEqual
|
||||||
of tyNil: result = isSubtype
|
of tyNil: result = isSubtype
|
||||||
of tyRef, tyPtr, tyProc, tyCString: result = isConvertible
|
of tyPtr, tyProc, tyCString: result = isConvertible
|
||||||
else: nil
|
else: nil
|
||||||
of tyString:
|
of tyString:
|
||||||
case a.kind
|
case a.kind
|
||||||
|
|
@ -664,21 +678,20 @@ proc sameMethodDispatcher(a, b: PSym): bool =
|
||||||
if aa.kind == nkSym and bb.kind == nkSym and aa.sym == bb.sym:
|
if aa.kind == nkSym and bb.kind == nkSym and aa.sym == bb.sym:
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode =
|
proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
|
||||||
var
|
initialBinding: PNode): PNode =
|
||||||
|
var
|
||||||
o: TOverloadIter
|
o: TOverloadIter
|
||||||
x, y, z: TCandidate
|
x, y, z: TCandidate
|
||||||
#liMessage(n.info, warnUser, renderTree(n));
|
#liMessage(n.info, warnUser, renderTree(n));
|
||||||
var sym = initOverloadIter(o, c, n.sons[0])
|
var sym = initOverloadIter(o, c, f)
|
||||||
result = nil
|
result = nil
|
||||||
if sym == nil: return
|
if sym == nil: return
|
||||||
initCandidate(x, sym.typ)
|
initCandidate(x, sym, initialBinding)
|
||||||
x.calleeSym = sym
|
initCandidate(y, sym, initialBinding)
|
||||||
initCandidate(y, sym.typ)
|
|
||||||
y.calleeSym = sym
|
|
||||||
while sym != nil:
|
while sym != nil:
|
||||||
if sym.kind in filter:
|
if sym.kind in filter:
|
||||||
initCandidate(z, sym.typ)
|
initCandidate(z, sym, initialBinding)
|
||||||
z.calleeSym = sym
|
z.calleeSym = sym
|
||||||
matches(c, n, z)
|
matches(c, n, z)
|
||||||
if z.state == csMatch:
|
if z.state == csMatch:
|
||||||
|
|
@ -689,7 +702,7 @@ proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode =
|
||||||
if cmp < 0: x = z # z is better than x
|
if cmp < 0: x = z # z is better than x
|
||||||
elif cmp == 0: y = z # z is as good as x
|
elif cmp == 0: y = z # z is as good as x
|
||||||
else: nil
|
else: nil
|
||||||
sym = nextOverloadIter(o, c, n.sons[0])
|
sym = nextOverloadIter(o, c, f)
|
||||||
if x.state == csEmpty:
|
if x.state == csEmpty:
|
||||||
# no overloaded proc found
|
# no overloaded proc found
|
||||||
# do not generate an error yet; the semantic checking will check for
|
# do not generate an error yet; the semantic checking will check for
|
||||||
|
|
@ -714,3 +727,16 @@ proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode =
|
||||||
result = x.call
|
result = x.call
|
||||||
result.sons[0] = newSymNode(x.calleeSym)
|
result.sons[0] = newSymNode(x.calleeSym)
|
||||||
result.typ = x.callee.sons[0]
|
result.typ = x.callee.sons[0]
|
||||||
|
|
||||||
|
proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode =
|
||||||
|
# process the bindings once:
|
||||||
|
var initialBinding: PNode
|
||||||
|
var f = n.sons[0]
|
||||||
|
if f.kind == nkBracketExpr:
|
||||||
|
# fill in the bindings:
|
||||||
|
initialBinding = f
|
||||||
|
f = f.sons[0]
|
||||||
|
else:
|
||||||
|
initialBinding = nil
|
||||||
|
result = semDirectCallWithBinding(c, n, f, filter, initialBinding)
|
||||||
|
|
||||||
|
|
|
||||||
106
rod/transf.nim
106
rod/transf.nim
|
|
@ -63,55 +63,55 @@ proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PSym =
|
||||||
incl(result.flags, sfFromGeneric)
|
incl(result.flags, sfFromGeneric)
|
||||||
|
|
||||||
proc transform(c: PTransf, n: PNode): PNode
|
proc transform(c: PTransf, n: PNode): PNode
|
||||||
#
|
|
||||||
#
|
# Transforming iterators into non-inlined versions is pretty hard, but
|
||||||
#Transforming iterators into non-inlined versions is pretty hard, but
|
# unavoidable for not bloating the code too much. If we had direct access to
|
||||||
#unavoidable for not bloating the code too much. If we had direct access to
|
# the program counter, things'd be much easier.
|
||||||
#the program counter, things'd be much easier.
|
# ::
|
||||||
#::
|
#
|
||||||
#
|
# iterator items(a: string): char =
|
||||||
# iterator items(a: string): char =
|
# var i = 0
|
||||||
# var i = 0
|
# while i < length(a):
|
||||||
# while i < length(a):
|
# yield a[i]
|
||||||
# yield a[i]
|
# inc(i)
|
||||||
# inc(i)
|
#
|
||||||
#
|
# for ch in items("hello world"): # `ch` is an iteration variable
|
||||||
# for ch in items("hello world"): # `ch` is an iteration variable
|
# echo(ch)
|
||||||
# echo(ch)
|
#
|
||||||
#
|
# Should be transformed into::
|
||||||
#Should be transformed into::
|
#
|
||||||
#
|
# type
|
||||||
# type
|
# TItemsClosure = record
|
||||||
# TItemsClosure = record
|
# i: int
|
||||||
# i: int
|
# state: int
|
||||||
# state: int
|
# proc items(a: string, c: var TItemsClosure): char =
|
||||||
# proc items(a: string, c: var TItemsClosure): char =
|
# case c.state
|
||||||
# case c.state
|
# of 0: goto L0 # very difficult without goto!
|
||||||
# of 0: goto L0 # very difficult without goto!
|
# of 1: goto L1 # can be implemented by GCC's computed gotos
|
||||||
# of 1: goto L1 # can be implemented by GCC's computed gotos
|
#
|
||||||
#
|
# block L0:
|
||||||
# block L0:
|
# c.i = 0
|
||||||
# c.i = 0
|
# while c.i < length(a):
|
||||||
# while c.i < length(a):
|
# c.state = 1
|
||||||
# c.state = 1
|
# return a[i]
|
||||||
# return a[i]
|
# block L1: inc(c.i)
|
||||||
# block L1: inc(c.i)
|
#
|
||||||
#
|
# More efficient, but not implementable::
|
||||||
#More efficient, but not implementable::
|
#
|
||||||
#
|
# type
|
||||||
# type
|
# TItemsClosure = record
|
||||||
# TItemsClosure = record
|
# i: int
|
||||||
# i: int
|
# pc: pointer
|
||||||
# pc: pointer
|
#
|
||||||
#
|
# proc items(a: string, c: var TItemsClosure): char =
|
||||||
# proc items(a: string, c: var TItemsClosure): char =
|
# goto c.pc
|
||||||
# goto c.pc
|
# c.i = 0
|
||||||
# c.i = 0
|
# while c.i < length(a):
|
||||||
# while c.i < length(a):
|
# c.pc = label1
|
||||||
# c.pc = label1
|
# return a[i]
|
||||||
# return a[i]
|
# label1: inc(c.i)
|
||||||
# label1: inc(c.i)
|
#
|
||||||
#
|
|
||||||
proc newAsgnStmt(c: PTransf, le, ri: PNode): PNode =
|
proc newAsgnStmt(c: PTransf, le, ri: PNode): PNode =
|
||||||
result = newNodeI(nkFastAsgn, ri.info)
|
result = newNodeI(nkFastAsgn, ri.info)
|
||||||
addSon(result, le)
|
addSon(result, le)
|
||||||
|
|
@ -290,8 +290,8 @@ proc transformConv(c: PTransf, n: PNode): PNode =
|
||||||
if not isOrdinalType(source):
|
if not isOrdinalType(source):
|
||||||
# XXX int64 -> float conversion?
|
# XXX int64 -> float conversion?
|
||||||
result = n
|
result = n
|
||||||
elif (firstOrd(dest) <= firstOrd(source)) and
|
elif firstOrd(dest) <= firstOrd(source) and
|
||||||
(lastOrd(source) <= lastOrd(dest)):
|
lastOrd(source) <= lastOrd(dest):
|
||||||
# BUGFIX: simply leave n as it is; we need a nkConv node,
|
# BUGFIX: simply leave n as it is; we need a nkConv node,
|
||||||
# but no range check:
|
# but no range check:
|
||||||
result = n
|
result = n
|
||||||
|
|
@ -540,8 +540,8 @@ proc getMergeOp(n: PNode): PSym =
|
||||||
|
|
||||||
proc flattenTreeAux(d, a: PNode, op: PSym) =
|
proc flattenTreeAux(d, a: PNode, op: PSym) =
|
||||||
var op2 = getMergeOp(a)
|
var op2 = getMergeOp(a)
|
||||||
if (op2 != nil) and
|
if op2 != nil and
|
||||||
((op2.id == op.id) or (op.magic != mNone) and (op2.magic == op.magic)):
|
(op2.id == op.id or op.magic != mNone and op2.magic == op.magic):
|
||||||
for i in countup(1, sonsLen(a) - 1): flattenTreeAux(d, a.sons[i], op)
|
for i in countup(1, sonsLen(a) - 1): flattenTreeAux(d, a.sons[i], op)
|
||||||
else:
|
else:
|
||||||
addSon(d, copyTree(a))
|
addSon(d, copyTree(a))
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ tcnstseq.nim;AngelikaAnneAnnaAnkaAnja
|
||||||
tconstr2.nim;69
|
tconstr2.nim;69
|
||||||
tcopy.nim;TEMP=C:\Programs\xyz\bin
|
tcopy.nim;TEMP=C:\Programs\xyz\bin
|
||||||
tcurrncy.nim;25
|
tcurrncy.nim;25
|
||||||
|
texplicitgeneric1.nim;Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13
|
||||||
tfinally.nim;came here
|
tfinally.nim;came here
|
||||||
tfloat1.nim;Error: unhandled exception: FPU operation caused an overflow [EFloatOverflow]
|
tfloat1.nim;Error: unhandled exception: FPU operation caused an overflow [EFloatOverflow]
|
||||||
tfloat2.nim;Error: unhandled exception: FPU operation caused a NaN result [EFloatInvalidOp]
|
tfloat2.nim;Error: unhandled exception: FPU operation caused a NaN result [EFloatInvalidOp]
|
||||||
|
|
|
||||||
|
11
web/news.txt
11
web/news.txt
|
|
@ -10,6 +10,13 @@ Bugfixes
|
||||||
|
|
||||||
- Bugfix: Command line parsing on Windows and ``os.parseCmdLine`` now adheres
|
- Bugfix: Command line parsing on Windows and ``os.parseCmdLine`` now adheres
|
||||||
to the same parsing rules as Microsoft's C/C++ startup code.
|
to the same parsing rules as Microsoft's C/C++ startup code.
|
||||||
|
- Bugfix: Passing a ``ref`` pointer to the untyped ``pointer`` type is invalid.
|
||||||
|
- Bugfix: Updated ``keyval`` example.
|
||||||
|
- Bugfix: ``system.splitChunk`` still contained code for debug output.
|
||||||
|
- Bugfix: ``times.getStartMilsecs`` uses ``gettimeofday`` for Posix times. It
|
||||||
|
used to use ``clock`` which has the wrong semantics.
|
||||||
|
- Bugfix: ``dialogs.ChooseFileToSave`` uses ``STOCK_SAVE`` instead of
|
||||||
|
``STOCK_OPEN`` for the GTK backend.
|
||||||
|
|
||||||
|
|
||||||
Changes affecting backwards compatibility
|
Changes affecting backwards compatibility
|
||||||
|
|
@ -24,6 +31,10 @@ Additions
|
||||||
|
|
||||||
- The ``{.compile: "file.c".}`` pragma uses a CRC check to see if the file
|
- The ``{.compile: "file.c".}`` pragma uses a CRC check to see if the file
|
||||||
needs to be recompiled.
|
needs to be recompiled.
|
||||||
|
- Added ``system.reopen``.
|
||||||
|
- Added ``system.getCurrentException``.
|
||||||
|
- Implemented explicit type arguments for generics.
|
||||||
|
- Implemented implicit type arguments for generics.
|
||||||
|
|
||||||
|
|
||||||
2010-03-14 Version 0.8.8 released
|
2010-03-14 Version 0.8.8 released
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue