mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 14:00:35 +00:00
explicit types for generic routines
This commit is contained in:
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.
|
||||
|
||||
|
||||
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
|
||||
=====================
|
||||
|
||||
@@ -216,71 +281,6 @@ the check whether the ref is on the stack is very cheap (only two
|
||||
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
|
||||
============================
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ Database support
|
||||
for other databases too.
|
||||
|
||||
* `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.
|
||||
|
||||
|
||||
|
||||
138
doc/theindex.txt
138
doc/theindex.txt
@@ -276,10 +276,10 @@ Index
|
||||
`ropes.html#115 <ropes.html#115>`_
|
||||
|
||||
`[]`:idx:
|
||||
`xmltree.html#114 <xmltree.html#114>`_
|
||||
`graphics.html#111 <graphics.html#111>`_
|
||||
|
||||
`[]`:idx:
|
||||
`graphics.html#111 <graphics.html#111>`_
|
||||
`xmltree.html#114 <xmltree.html#114>`_
|
||||
|
||||
`[]=`:idx:
|
||||
`strtabs.html#106 <strtabs.html#106>`_
|
||||
@@ -731,12 +731,6 @@ Index
|
||||
`clonglong`:idx:
|
||||
`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:
|
||||
* `sockets.html#121 <sockets.html#121>`_
|
||||
* `lexbase.html#105 <lexbase.html#105>`_
|
||||
@@ -746,8 +740,14 @@ Index
|
||||
* `zipfiles.html#103 <zipfiles.html#103>`_
|
||||
* `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:
|
||||
`system.html#511 <system.html#511>`_
|
||||
`system.html#512 <system.html#512>`_
|
||||
|
||||
`closure`:idx:
|
||||
`manual.html#177 <manual.html#177>`_
|
||||
@@ -1350,8 +1350,8 @@ Index
|
||||
`system.html#392 <system.html#392>`_
|
||||
|
||||
`cstringArrayToSeq`:idx:
|
||||
* `system.html#539 <system.html#539>`_
|
||||
* `system.html#540 <system.html#540>`_
|
||||
* `system.html#541 <system.html#541>`_
|
||||
|
||||
`CSV`:idx:
|
||||
`parsecsv.html#101 <parsecsv.html#101>`_
|
||||
@@ -1777,8 +1777,7 @@ Index
|
||||
* `strutils.html#157 <strutils.html#157>`_
|
||||
|
||||
`deleteStr`:idx:
|
||||
* `strutils.html#124 <strutils.html#124>`_
|
||||
* `strutils.html#158 <strutils.html#158>`_
|
||||
`strutils.html#124 <strutils.html#124>`_
|
||||
|
||||
`dfn`:idx:
|
||||
`xmlgen.html#125 <xmlgen.html#125>`_
|
||||
@@ -1894,7 +1893,7 @@ Index
|
||||
* `db_sqlite.html#104 <db_sqlite.html#104>`_
|
||||
|
||||
`editDistance`:idx:
|
||||
`strutils.html#166 <strutils.html#166>`_
|
||||
`strutils.html#165 <strutils.html#165>`_
|
||||
|
||||
`EDivByZero`:idx:
|
||||
`system.html#147 <system.html#147>`_
|
||||
@@ -2020,7 +2019,7 @@ Index
|
||||
`endb.html#102 <endb.html#102>`_
|
||||
|
||||
`EndOfFile`:idx:
|
||||
* `system.html#513 <system.html#513>`_
|
||||
* `system.html#514 <system.html#514>`_
|
||||
* `lexbase.html#101 <lexbase.html#101>`_
|
||||
|
||||
`endsWith`:idx:
|
||||
@@ -2132,7 +2131,7 @@ Index
|
||||
|
||||
`escape`:idx:
|
||||
* `manual.html#133 <manual.html#133>`_
|
||||
* `strutils.html#163 <strutils.html#163>`_
|
||||
* `strutils.html#162 <strutils.html#162>`_
|
||||
* `xmltree.html#122 <xmltree.html#122>`_
|
||||
|
||||
`escape sequences`:idx:
|
||||
@@ -2373,7 +2372,7 @@ Index
|
||||
`mysql.html#218 <mysql.html#218>`_
|
||||
|
||||
`fileHandle`:idx:
|
||||
`system.html#538 <system.html#538>`_
|
||||
`system.html#539 <system.html#539>`_
|
||||
|
||||
`fileNewer`:idx:
|
||||
`os.html#119 <os.html#119>`_
|
||||
@@ -2433,7 +2432,7 @@ Index
|
||||
`macros.html#130 <macros.html#130>`_
|
||||
|
||||
`FlushFile`:idx:
|
||||
`system.html#515 <system.html#515>`_
|
||||
`system.html#516 <system.html#516>`_
|
||||
|
||||
`for`:idx:
|
||||
* `manual.html#214 <manual.html#214>`_
|
||||
@@ -2594,10 +2593,10 @@ Index
|
||||
`os.html#162 <os.html#162>`_
|
||||
|
||||
`getFilePos`:idx:
|
||||
`system.html#535 <system.html#535>`_
|
||||
`system.html#536 <system.html#536>`_
|
||||
|
||||
`getFileSize`:idx:
|
||||
* `system.html#527 <system.html#527>`_
|
||||
* `system.html#528 <system.html#528>`_
|
||||
* `os.html#171 <os.html#171>`_
|
||||
|
||||
`getFreeMem`:idx:
|
||||
@@ -2866,13 +2865,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>`_
|
||||
|
||||
`htmlTag`:idx:
|
||||
* `htmlparser.html#105 <htmlparser.html#105>`_
|
||||
* `htmlparser.html#106 <htmlparser.html#106>`_
|
||||
@@ -2914,24 +2913,24 @@ Index
|
||||
`ident=`:idx:
|
||||
`macros.html#132 <macros.html#132>`_
|
||||
|
||||
`IdentChars`:idx:
|
||||
`strutils.html#105 <strutils.html#105>`_
|
||||
|
||||
`identChars`:idx:
|
||||
`pegs.html#132 <pegs.html#132>`_
|
||||
|
||||
`IdentChars`:idx:
|
||||
`strutils.html#105 <strutils.html#105>`_
|
||||
|
||||
`identifier`:idx:
|
||||
`manual.html#105 <manual.html#105>`_
|
||||
|
||||
`Identifiers`:idx:
|
||||
`manual.html#116 <manual.html#116>`_
|
||||
|
||||
`IdentStartChars`:idx:
|
||||
`strutils.html#106 <strutils.html#106>`_
|
||||
|
||||
`identStartChars`:idx:
|
||||
`pegs.html#133 <pegs.html#133>`_
|
||||
|
||||
`IdentStartChars`:idx:
|
||||
`strutils.html#106 <strutils.html#106>`_
|
||||
|
||||
`if`:idx:
|
||||
`manual.html#189 <manual.html#189>`_
|
||||
|
||||
@@ -3018,7 +3017,7 @@ Index
|
||||
* `db_sqlite.html#115 <db_sqlite.html#115>`_
|
||||
|
||||
`insertSep`:idx:
|
||||
`strutils.html#162 <strutils.html#162>`_
|
||||
`strutils.html#161 <strutils.html#161>`_
|
||||
|
||||
`int`:idx:
|
||||
`system.html#101 <system.html#101>`_
|
||||
@@ -3208,8 +3207,8 @@ Index
|
||||
`nimrodc.html#103 <nimrodc.html#103>`_
|
||||
|
||||
`lines`:idx:
|
||||
* `system.html#536 <system.html#536>`_
|
||||
* `system.html#537 <system.html#537>`_
|
||||
* `system.html#538 <system.html#538>`_
|
||||
|
||||
`lineTrace`:idx:
|
||||
`nimrodc.html#105 <nimrodc.html#105>`_
|
||||
@@ -3233,13 +3232,13 @@ Index
|
||||
`LoadLib`:idx:
|
||||
`dynlib.html#102 <dynlib.html#102>`_
|
||||
|
||||
`loadXML`:idx:
|
||||
`xmldomparser.html#104 <xmldomparser.html#104>`_
|
||||
|
||||
`loadXml`:idx:
|
||||
* `xmlparser.html#104 <xmlparser.html#104>`_
|
||||
* `xmlparser.html#105 <xmlparser.html#105>`_
|
||||
|
||||
`loadXML`:idx:
|
||||
`xmldomparser.html#104 <xmldomparser.html#104>`_
|
||||
|
||||
`loadXMLFile`:idx:
|
||||
`xmldomparser.html#105 <xmldomparser.html#105>`_
|
||||
|
||||
@@ -3965,12 +3964,12 @@ Index
|
||||
`nan`:idx:
|
||||
`system.html#441 <system.html#441>`_
|
||||
|
||||
`natural`:idx:
|
||||
`pegs.html#135 <pegs.html#135>`_
|
||||
|
||||
`Natural`:idx:
|
||||
`system.html#134 <system.html#134>`_
|
||||
|
||||
`natural`:idx:
|
||||
`pegs.html#135 <pegs.html#135>`_
|
||||
|
||||
`neginf`:idx:
|
||||
`system.html#440 <system.html#440>`_
|
||||
|
||||
@@ -4056,13 +4055,13 @@ Index
|
||||
`newIntLitNode`:idx:
|
||||
`macros.html#142 <macros.html#142>`_
|
||||
|
||||
`newLine`:idx:
|
||||
`pegs.html#122 <pegs.html#122>`_
|
||||
|
||||
`newline`:idx:
|
||||
* `manual.html#121 <manual.html#121>`_
|
||||
* `pegs.html#121 <pegs.html#121>`_
|
||||
|
||||
`newLine`:idx:
|
||||
`pegs.html#122 <pegs.html#122>`_
|
||||
|
||||
`NewLines`:idx:
|
||||
`lexbase.html#102 <lexbase.html#102>`_
|
||||
|
||||
@@ -4246,12 +4245,12 @@ Index
|
||||
`ord`:idx:
|
||||
`system.html#182 <system.html#182>`_
|
||||
|
||||
`ordinal`:idx:
|
||||
`tut1.html#114 <tut1.html#114>`_
|
||||
|
||||
`Ordinal`:idx:
|
||||
`system.html#114 <system.html#114>`_
|
||||
|
||||
`ordinal`:idx:
|
||||
`tut1.html#114 <tut1.html#114>`_
|
||||
|
||||
`Ordinal types`:idx:
|
||||
`manual.html#142 <manual.html#142>`_
|
||||
|
||||
@@ -4313,12 +4312,12 @@ Index
|
||||
`parseColor`:idx:
|
||||
`colors.html#249 <colors.html#249>`_
|
||||
|
||||
`parseFloat`:idx:
|
||||
`parseutils.html#111 <parseutils.html#111>`_
|
||||
|
||||
`ParseFloat`:idx:
|
||||
`strutils.html#144 <strutils.html#144>`_
|
||||
|
||||
`parseFloat`:idx:
|
||||
`parseutils.html#111 <parseutils.html#111>`_
|
||||
|
||||
`parseHex`:idx:
|
||||
`parseutils.html#101 <parseutils.html#101>`_
|
||||
|
||||
@@ -4332,17 +4331,17 @@ Index
|
||||
`parseIdent`:idx:
|
||||
`parseutils.html#103 <parseutils.html#103>`_
|
||||
|
||||
`ParseInt`:idx:
|
||||
`strutils.html#142 <strutils.html#142>`_
|
||||
|
||||
`parseInt`:idx:
|
||||
`parseutils.html#109 <parseutils.html#109>`_
|
||||
|
||||
`ParseInt`:idx:
|
||||
`strutils.html#142 <strutils.html#142>`_
|
||||
|
||||
`parseOct`:idx:
|
||||
`parseutils.html#102 <parseutils.html#102>`_
|
||||
|
||||
`ParseOctInt`:idx:
|
||||
`strutils.html#159 <strutils.html#159>`_
|
||||
`strutils.html#158 <strutils.html#158>`_
|
||||
|
||||
`parsePeg`:idx:
|
||||
`pegs.html#154 <pegs.html#154>`_
|
||||
@@ -4644,8 +4643,7 @@ Index
|
||||
`httpclient.html#109 <httpclient.html#109>`_
|
||||
|
||||
`PostgreSQL`:idx:
|
||||
* `db_postgres.html#101 <db_postgres.html#101>`_
|
||||
* `db_sqlite.html#101 <db_sqlite.html#101>`_
|
||||
`db_postgres.html#101 <db_postgres.html#101>`_
|
||||
|
||||
`pow`:idx:
|
||||
`math.html#132 <math.html#132>`_
|
||||
@@ -4878,23 +4876,23 @@ Index
|
||||
`streams.html#106 <streams.html#106>`_
|
||||
|
||||
`readBuffer`:idx:
|
||||
`system.html#530 <system.html#530>`_
|
||||
`system.html#531 <system.html#531>`_
|
||||
|
||||
`ReadBytes`:idx:
|
||||
`system.html#528 <system.html#528>`_
|
||||
`system.html#529 <system.html#529>`_
|
||||
|
||||
`readChar`:idx:
|
||||
* `system.html#514 <system.html#514>`_
|
||||
* `system.html#515 <system.html#515>`_
|
||||
* `streams.html#105 <streams.html#105>`_
|
||||
|
||||
`ReadChars`:idx:
|
||||
`system.html#529 <system.html#529>`_
|
||||
`system.html#530 <system.html#530>`_
|
||||
|
||||
`readData`:idx:
|
||||
`cgi.html#109 <cgi.html#109>`_
|
||||
|
||||
`readFile`:idx:
|
||||
`system.html#516 <system.html#516>`_
|
||||
`system.html#517 <system.html#517>`_
|
||||
|
||||
`readFloat32`:idx:
|
||||
`streams.html#111 <streams.html#111>`_
|
||||
@@ -4915,7 +4913,7 @@ Index
|
||||
`streams.html#107 <streams.html#107>`_
|
||||
|
||||
`readLine`:idx:
|
||||
* `system.html#524 <system.html#524>`_
|
||||
* `system.html#525 <system.html#525>`_
|
||||
* `streams.html#114 <streams.html#114>`_
|
||||
|
||||
`readRow`:idx:
|
||||
@@ -5041,6 +5039,9 @@ Index
|
||||
* `regexprs.html#117 <regexprs.html#117>`_
|
||||
* `re.html#131 <re.html#131>`_
|
||||
|
||||
`reopen`:idx:
|
||||
`system.html#511 <system.html#511>`_
|
||||
|
||||
`repeatChar`:idx:
|
||||
`strutils.html#147 <strutils.html#147>`_
|
||||
|
||||
@@ -5256,7 +5257,7 @@ Index
|
||||
`os.html#163 <os.html#163>`_
|
||||
|
||||
`setFilePos`:idx:
|
||||
`system.html#534 <system.html#534>`_
|
||||
`system.html#535 <system.html#535>`_
|
||||
|
||||
`SET_FLAG`:idx:
|
||||
`mysql.html#135 <mysql.html#135>`_
|
||||
@@ -5378,6 +5379,9 @@ Index
|
||||
* `db_postgres.html#106 <db_postgres.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.html#261 <sqlite3.html#261>`_
|
||||
|
||||
@@ -6401,7 +6405,7 @@ Index
|
||||
`system.html#411 <system.html#411>`_
|
||||
|
||||
`toBin`:idx:
|
||||
`strutils.html#161 <strutils.html#161>`_
|
||||
`strutils.html#160 <strutils.html#160>`_
|
||||
|
||||
`TObject`:idx:
|
||||
`system.html#136 <system.html#136>`_
|
||||
@@ -6421,7 +6425,7 @@ Index
|
||||
* `unicode.html#111 <unicode.html#111>`_
|
||||
|
||||
`toOct`:idx:
|
||||
`strutils.html#160 <strutils.html#160>`_
|
||||
`strutils.html#159 <strutils.html#159>`_
|
||||
|
||||
`toOctal`:idx:
|
||||
`strutils.html#125 <strutils.html#125>`_
|
||||
@@ -6722,10 +6726,10 @@ Index
|
||||
`cgi.html#110 <cgi.html#110>`_
|
||||
|
||||
`validEmailAddress`:idx:
|
||||
`strutils.html#164 <strutils.html#164>`_
|
||||
`strutils.html#163 <strutils.html#163>`_
|
||||
|
||||
`validIdentifier`:idx:
|
||||
`strutils.html#165 <strutils.html#165>`_
|
||||
`strutils.html#164 <strutils.html#164>`_
|
||||
|
||||
`Var`:idx:
|
||||
`manual.html#187 <manual.html#187>`_
|
||||
@@ -6788,32 +6792,32 @@ Index
|
||||
`times.html#118 <times.html#118>`_
|
||||
|
||||
`write`:idx:
|
||||
* `system.html#517 <system.html#517>`_
|
||||
* `system.html#518 <system.html#518>`_
|
||||
* `system.html#519 <system.html#519>`_
|
||||
* `system.html#520 <system.html#520>`_
|
||||
* `system.html#521 <system.html#521>`_
|
||||
* `system.html#522 <system.html#522>`_
|
||||
* `system.html#523 <system.html#523>`_
|
||||
* `system.html#524 <system.html#524>`_
|
||||
* `streams.html#103 <streams.html#103>`_
|
||||
* `streams.html#104 <streams.html#104>`_
|
||||
* `ropes.html#118 <ropes.html#118>`_
|
||||
|
||||
`writeBuffer`:idx:
|
||||
`system.html#533 <system.html#533>`_
|
||||
`system.html#534 <system.html#534>`_
|
||||
|
||||
`writeBytes`:idx:
|
||||
`system.html#531 <system.html#531>`_
|
||||
`system.html#532 <system.html#532>`_
|
||||
|
||||
`writeChars`:idx:
|
||||
`system.html#532 <system.html#532>`_
|
||||
`system.html#533 <system.html#533>`_
|
||||
|
||||
`writeContentType`:idx:
|
||||
`cgi.html#144 <cgi.html#144>`_
|
||||
|
||||
`writeln`:idx:
|
||||
* `system.html#525 <system.html#525>`_
|
||||
* `system.html#526 <system.html#526>`_
|
||||
* `system.html#527 <system.html#527>`_
|
||||
|
||||
`WriteStyled`:idx:
|
||||
`terminal.html#112 <terminal.html#112>`_
|
||||
|
||||
@@ -3,7 +3,7 @@ import re
|
||||
|
||||
for x in lines("myfile.txt"):
|
||||
if x =~ re"(\w+)=(.*)":
|
||||
echo "Key: ", matches[1],
|
||||
" Value: ", matches[2]
|
||||
echo "Key: ", matches[0],
|
||||
" Value: ", matches[1]
|
||||
|
||||
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
|
||||
|
||||
## This module implements portable dialogs for Nimrod; the implementation
|
||||
## builds on the GTK interface. On Windows, native dialogs are shown if
|
||||
## appropriate.
|
||||
## builds on the GTK interface. On Windows, native dialogs are shown instead.
|
||||
|
||||
import
|
||||
glib2, gtk2
|
||||
@@ -174,7 +173,7 @@ proc ChooseFileToSave*(window: PWindow, root: string = ""): string =
|
||||
var chooser = file_chooser_dialog_new("Save File", window,
|
||||
FILE_CHOOSER_ACTION_SAVE,
|
||||
STOCK_CANCEL, RESPONSE_CANCEL,
|
||||
STOCK_OPEN, RESPONSE_OK, nil)
|
||||
STOCK_SAVE, RESPONSE_OK, nil)
|
||||
if root.len > 0:
|
||||
discard set_current_folder(chooser, root)
|
||||
set_do_overwrite_confirmation(chooser, true)
|
||||
|
||||
@@ -24,6 +24,13 @@ __TINYC__
|
||||
|
||||
#if !defined(__TINYC__)
|
||||
# include <math.h>
|
||||
#else
|
||||
/*# define __GNUC__ 3
|
||||
# define GCC_MAJOR 4
|
||||
# define __GNUC_MINOR__ 4
|
||||
# define __GNUC_PATCHLEVEL__ 5 */
|
||||
|
||||
# define __DECLSPEC_SUPPORTED 1
|
||||
#endif
|
||||
|
||||
/* calling convention mess ----------------------------------------------- */
|
||||
|
||||
@@ -953,8 +953,8 @@ proc parseCmdLine*(c: string): seq[string] =
|
||||
## causing a literal double quotation mark (") to be placed in argv.
|
||||
##
|
||||
## On Posix systems, it uses the following parsing rules:
|
||||
## components are separated by
|
||||
## whitespace unless the whitespace occurs within ``"`` or ``'`` quotes.
|
||||
## Components are separated by whitespace unless the whitespace
|
||||
## occurs within ``"`` or ``'`` quotes.
|
||||
result = @[]
|
||||
var i = 0
|
||||
var a = ""
|
||||
@@ -963,6 +963,7 @@ proc parseCmdLine*(c: string): seq[string] =
|
||||
while c[i] == ' ' or c[i] == '\t': inc(i)
|
||||
when defined(windows):
|
||||
# parse a single argument according to the above rules:
|
||||
if c[i] == '\0': break
|
||||
var inQuote = false
|
||||
while true:
|
||||
case c[i]
|
||||
@@ -971,7 +972,7 @@ proc parseCmdLine*(c: string): seq[string] =
|
||||
var j = i
|
||||
while c[j] == '\\': inc(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:
|
||||
i = j
|
||||
else:
|
||||
|
||||
@@ -26,6 +26,19 @@ type
|
||||
when defined(posix):
|
||||
type
|
||||
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):
|
||||
when defined(vcc):
|
||||
# newest version of Visual C++ defines time_t to be of 64 bits
|
||||
@@ -147,7 +160,7 @@ when not defined(ECMAScript):
|
||||
PTimeInfo = ptr structTM
|
||||
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 {.
|
||||
importc: "localtime", header: "<time.h>".}
|
||||
@@ -197,9 +210,17 @@ when not defined(ECMAScript):
|
||||
return toBiggestInt(difftime(a, b))
|
||||
|
||||
proc getStartMilsecs(): int =
|
||||
#echo "clocks per sec: ", clocksPerSec
|
||||
#echo "clocks per sec: ", clocksPerSec, "clock: ", int(clock())
|
||||
#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 getLocalTime(t: TTime): TTimeInfo =
|
||||
|
||||
@@ -1176,3 +1176,5 @@ proc cmpRunesIgnoreCase*(a, b: string): int =
|
||||
if result != 0: return
|
||||
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.}
|
||||
## retrieves the error message that was attached to the current
|
||||
## 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:
|
||||
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.
|
||||
|
||||
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.}
|
||||
## Closes the file.
|
||||
## **Deprecated since version 0.8.0**: Use `close` instead.
|
||||
@@ -1554,6 +1564,7 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||
else:
|
||||
result = n.sons[n.len]
|
||||
|
||||
include "system/systhread"
|
||||
include "system/mm"
|
||||
include "system/sysstr"
|
||||
include "system/assign"
|
||||
@@ -1564,6 +1575,10 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||
if excHandler == nil: return ""
|
||||
return $excHandler.exc.msg
|
||||
|
||||
proc getCurrentException(): ref E_Base =
|
||||
if excHandler != nil:
|
||||
result = excHandler.exc
|
||||
|
||||
{.push stack_trace: off.}
|
||||
when defined(endb):
|
||||
include "system/debugger"
|
||||
|
||||
@@ -376,10 +376,10 @@ proc freeBigChunk(a: var TAllocator, c: PBigChunk) =
|
||||
|
||||
proc splitChunk(a: var TAllocator, c: PBigChunk, size: int) =
|
||||
var rest = cast[PBigChunk](cast[TAddress](c) +% size)
|
||||
if rest in a.freeChunksList:
|
||||
c_fprintf(c_stdout, "to add: %p\n", rest)
|
||||
writeFreeList(allocator)
|
||||
assert false
|
||||
assert(rest notin a.freeChunksList)
|
||||
# c_fprintf(c_stdout, "to add: %p\n", rest)
|
||||
# writeFreeList(allocator)
|
||||
# assert false
|
||||
rest.size = c.size - size
|
||||
rest.used = false
|
||||
rest.next = nil
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -478,6 +478,10 @@ proc gcMark(p: pointer) {.inline.} =
|
||||
cell.refcount = cell.refcount +% rcIncrement
|
||||
add(gch.decStack, cell)
|
||||
|
||||
proc markThreadStacks(gch: var TGcHeap) =
|
||||
when isMultiThreaded:
|
||||
nil
|
||||
|
||||
# ----------------- stack management --------------------------------------
|
||||
# inspired from Smart Eiffel
|
||||
|
||||
@@ -613,6 +617,7 @@ proc collectCT(gch: var TGcHeap) =
|
||||
gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
|
||||
assert(gch.decStack.len == 0)
|
||||
markStackAndRegisters(gch)
|
||||
markThreadStacks(gch)
|
||||
gch.stat.maxStackCells = max(gch.stat.maxStackCells, gch.decStack.len)
|
||||
inc(gch.stat.stackScans)
|
||||
collectZCT(gch)
|
||||
|
||||
@@ -27,6 +27,9 @@ proc strlen(c: cstring): int {.importc: "strlen", nodecl.}
|
||||
proc setvbuf(stream: TFile, buf: pointer, typ, size: cint): cint {.
|
||||
importc, nodecl.}
|
||||
|
||||
proc freopen(path, mode: cstring, stream: TFile): TFile {.importc: "freopen",
|
||||
nodecl.}
|
||||
|
||||
proc write(f: TFile, c: cstring) = fputs(c, f)
|
||||
|
||||
var
|
||||
@@ -112,9 +115,7 @@ const
|
||||
proc Open(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead,
|
||||
bufSize: int = -1): Bool =
|
||||
var
|
||||
p: pointer
|
||||
p = fopen(filename, FormatOpen[mode])
|
||||
var p: pointer = fopen(filename, FormatOpen[mode])
|
||||
result = (p != nil)
|
||||
f = cast[TFile](p)
|
||||
if bufSize > 0:
|
||||
@@ -123,6 +124,10 @@ proc Open(f: var TFile, filename: string,
|
||||
elif bufSize == 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 {.
|
||||
importc: pccHack & "fdopen", header: "<stdio.h>".}
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ elif defined(macosx):
|
||||
LibName = "libSDL-1.2.0.dylib"
|
||||
else:
|
||||
const
|
||||
LibName = "libSDL.so"
|
||||
LibName = "libSDL.so(|.1|.0)"
|
||||
const
|
||||
MAJOR_VERSION* = 1'i8
|
||||
MINOR_VERSION* = 2'i8
|
||||
|
||||
@@ -163,7 +163,7 @@ elif defined(macosx):
|
||||
ttfLibName = "libSDL_ttf-2.0.0.dylib"
|
||||
else:
|
||||
const
|
||||
ttfLibName = "libSDL_ttf.so"
|
||||
ttfLibName = "libSDL_ttf.so(|.1|.0)"
|
||||
const
|
||||
MAJOR_VERSION* = 2'i8
|
||||
MINOR_VERSION* = 0'i8
|
||||
|
||||
@@ -417,23 +417,20 @@ proc renderRstToRst(d: PDoc, n: PRstNode): PRope =
|
||||
# debugging, but most code is already debugged...
|
||||
const
|
||||
lvlToChar: array[0..8, char] = ['!', '=', '-', '~', '`', '<', '*', '|', '+']
|
||||
var
|
||||
L: int
|
||||
ind: PRope
|
||||
result = nil
|
||||
if n == nil: return
|
||||
ind = toRope(repeatChar(d.indent))
|
||||
var ind = toRope(repeatChar(d.indent))
|
||||
case n.kind
|
||||
of rnInner:
|
||||
result = renderRstSons(d, n)
|
||||
of rnHeadline:
|
||||
result = renderRstSons(d, n)
|
||||
L = ropeLen(result)
|
||||
var L = ropeLen(result)
|
||||
result = ropef("$n$1$2$n$1$3",
|
||||
[ind, result, toRope(repeatChar(L, lvlToChar[n.level]))])
|
||||
of rnOverline:
|
||||
result = renderRstSons(d, n)
|
||||
L = ropeLen(result)
|
||||
var L = ropeLen(result)
|
||||
result = ropef("$n$1$3$n$1$2$n$1$3",
|
||||
[ind, result, toRope(repeatChar(L, lvlToChar[n.level]))])
|
||||
of rnTransition:
|
||||
@@ -464,7 +461,7 @@ proc renderRstToRst(d: PDoc, n: PRstNode): PRope =
|
||||
dec(d.indent, 2)
|
||||
of rnField:
|
||||
result = renderRstToRst(d, n.sons[0])
|
||||
L = max(ropeLen(result) + 3, 30)
|
||||
var L = max(ropeLen(result) + 3, 30)
|
||||
inc(d.indent, L)
|
||||
result = ropef("$n$1:$2:$3$4", [ind, result, toRope(
|
||||
repeatChar(L - ropeLen(result) - 2)), renderRstToRst(d, n.sons[1])])
|
||||
|
||||
@@ -714,8 +714,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
var a = result
|
||||
result = newNodeIT(nkIntLit, n.info, n.typ)
|
||||
case a.kind
|
||||
of nkEmpty..nkNilLit:
|
||||
nil
|
||||
of nkEmpty..nkNilLit: nil
|
||||
else: result.intVal = sonsLen(a)
|
||||
of mNChild:
|
||||
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)
|
||||
if s != nil and s.kind in {skProc, skMethod, skConverter, skIterator}:
|
||||
# type parameters: partial generic specialization
|
||||
# XXX: too implement!
|
||||
internalError(n.info, "explicit generic instantation not implemented")
|
||||
result = partialSpecialization(c, n, s)
|
||||
else:
|
||||
result = semArrayAccess(c, n, flags)
|
||||
|
||||
@@ -1,29 +1,28 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# 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
|
||||
proc searchInstTypes(tab: TIdTable, key: PType): PType =
|
||||
var
|
||||
t: PType
|
||||
match: bool
|
||||
# returns nil if we need to declare this type
|
||||
result = PType(IdTableGet(tab, key))
|
||||
if (result == nil) and (tab.counter > 0):
|
||||
# we have to do a slow linear search because types may need
|
||||
# to be compared by their structure:
|
||||
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 key.containerId == t.containerID:
|
||||
match = true
|
||||
var match = true
|
||||
for j in countup(0, sonsLen(t) - 1):
|
||||
# XXX sameType is not really correct for nested generics?
|
||||
if not sameType(t.sons[j], key.sons[j]):
|
||||
@@ -39,20 +38,16 @@ proc containsGenericType(t: PType): bool =
|
||||
result = iterOverType(t, containsGenericTypeIter, nil)
|
||||
|
||||
proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
|
||||
var
|
||||
s, q: PSym
|
||||
t: PType
|
||||
a: PNode
|
||||
if (n.kind != nkGenericParams):
|
||||
InternalError(n.info, "instantiateGenericParamList; no generic params")
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
a = n.sons[i]
|
||||
var a = n.sons[i]
|
||||
if a.kind != nkSym:
|
||||
InternalError(a.info, "instantiateGenericParamList; no symbol")
|
||||
q = a.sym
|
||||
var q = a.sym
|
||||
if not (q.typ.kind in {tyTypeDesc, tyGenericParam}): continue
|
||||
s = newSym(skType, q.name, getCurrOwner())
|
||||
t = PType(IdTableGet(pt, q.typ))
|
||||
var s = newSym(skType, q.name, getCurrOwner())
|
||||
var t = PType(IdTableGet(pt, q.typ))
|
||||
if t == nil: liMessage(a.info, errCannotInstantiateX, s.name.s)
|
||||
if (t.kind == tyGenericParam):
|
||||
InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
|
||||
@@ -60,27 +55,26 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
|
||||
addDecl(c, s)
|
||||
|
||||
proc GenericCacheGet(c: PContext, genericSym, instSym: PSym): PSym =
|
||||
var a, b: PSym
|
||||
result = nil
|
||||
for i in countup(0, sonsLen(c.generics) - 1):
|
||||
if c.generics.sons[i].kind != nkExprEqExpr:
|
||||
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:
|
||||
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 gVerbosity > 0 then
|
||||
# MessageOut('found in cache: ' + getProcHeader(instSym));
|
||||
return b
|
||||
|
||||
proc GenericCacheAdd(c: PContext, genericSym, instSym: PSym) =
|
||||
var n: PNode
|
||||
n = newNode(nkExprEqExpr)
|
||||
var n = newNode(nkExprEqExpr)
|
||||
addSon(n, newSymNode(genericSym))
|
||||
addSon(n, newSymNode(instSym))
|
||||
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
|
||||
var
|
||||
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")
|
||||
inc(c.InstCounter)
|
||||
oldP = c.p # restore later
|
||||
# NOTE: for access of private fields within generics from a different module
|
||||
# and other identifiers we fake the current module temporarily!
|
||||
# NOTE: for access of private fields within generics from a different module
|
||||
# and other identifiers we fake the current module temporarily!
|
||||
oldMod = c.module
|
||||
c.module = getModule(fn)
|
||||
result = copySym(fn, false)
|
||||
@@ -151,8 +145,6 @@ type
|
||||
proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType
|
||||
proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
|
||||
proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
||||
var length: int
|
||||
result = nil
|
||||
if n != nil:
|
||||
result = copyNode(n)
|
||||
result.typ = ReplaceTypeVarsT(cl, n.typ)
|
||||
@@ -162,7 +154,7 @@ proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
||||
of nkSym:
|
||||
result.sym = ReplaceTypeVarsS(cl, n.sym)
|
||||
else:
|
||||
length = sonsLen(n)
|
||||
var length = sonsLen(n)
|
||||
if length > 0:
|
||||
newSons(result, length)
|
||||
for i in countup(0, length - 1):
|
||||
@@ -172,7 +164,7 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
|
||||
if s == nil:
|
||||
return nil
|
||||
result = PSym(idTableGet(cl.symMap, s))
|
||||
if (result == nil):
|
||||
if result == nil:
|
||||
result = copySym(s, false)
|
||||
incl(result.flags, sfFromGeneric)
|
||||
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.n = ReplaceTypeVarsN(cl, result.n)
|
||||
if result.Kind in GenericTypes:
|
||||
liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName)) #writeln(output, ropeToStr(Typetoyaml(result)));
|
||||
#checkConstructedType(cl.info, result);
|
||||
liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
|
||||
#writeln(output, ropeToStr(Typetoyaml(result)))
|
||||
#checkConstructedType(cl.info, result)
|
||||
|
||||
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
|
||||
var cl: TReplTypeVars
|
||||
@@ -240,7 +233,8 @@ proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
|
||||
cl.c = c
|
||||
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
|
||||
InitIdTable(cl.symMap)
|
||||
copyIdTable(cl.typeMap, pt)
|
||||
@@ -251,4 +245,9 @@ proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode, t: PType): PTyp
|
||||
popInfoContext()
|
||||
|
||||
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
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# this module does the semantic checking of statements
|
||||
|
||||
proc semExprNoType(c: PContext, n: PNode): PNode =
|
||||
@@ -267,14 +268,13 @@ proc SemReturn(c: PContext, n: PNode): PNode =
|
||||
liMessage(n.info, errCannotReturnExpr)
|
||||
|
||||
proc SemYield(c: PContext, n: PNode): PNode =
|
||||
var restype: PType
|
||||
result = n
|
||||
checkSonsLen(n, 1)
|
||||
if (c.p.owner == nil) or (c.p.owner.kind != skIterator):
|
||||
liMessage(n.info, errYieldNotAllowedHere)
|
||||
if (n.sons[0] != nil):
|
||||
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):
|
||||
n.sons[0] = fitNode(c, restype, n.sons[0])
|
||||
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.typ = newTypeS(tyGenericParam, c)
|
||||
else:
|
||||
# not a type param, but an expression
|
||||
s = newSymS(skGenericParam, a.sons[j], c)
|
||||
s.typ = typ
|
||||
s.ast = def
|
||||
|
||||
135
rod/semtypes.nim
135
rod/semtypes.nim
@@ -6,6 +6,7 @@
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# this module does the semantic checking of type declarations
|
||||
|
||||
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
|
||||
@@ -63,10 +64,9 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
inc(counter)
|
||||
|
||||
proc semSet(c: PContext, n: PNode, prev: PType): PType =
|
||||
var base: PType
|
||||
result = newOrPrevType(tySet, prev, c)
|
||||
if sonsLen(n) == 2:
|
||||
base = semTypeNode(c, n.sons[1], nil)
|
||||
var base = semTypeNode(c, n.sons[1], nil)
|
||||
addSon(result, base)
|
||||
if base.kind == tyGenericInst: base = lastSon(base)
|
||||
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,
|
||||
prev: PType): PType =
|
||||
var base: PType
|
||||
result = newOrPrevType(kind, prev, c)
|
||||
if sonsLen(n) == 2:
|
||||
base = semTypeNode(c, n.sons[1], nil)
|
||||
var base = semTypeNode(c, n.sons[1], nil)
|
||||
addSon(result, base)
|
||||
else:
|
||||
liMessage(n.info, errXExpectsOneTypeParam, kindStr)
|
||||
|
||||
proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
|
||||
prev: PType): PType =
|
||||
var base: PType
|
||||
result = newOrPrevType(kind, prev, c)
|
||||
if sonsLen(n) == 1:
|
||||
base = semTypeNode(c, n.sons[0], nil)
|
||||
var base = semTypeNode(c, n.sons[0], nil)
|
||||
addSon(result, base)
|
||||
else:
|
||||
liMessage(n.info, errXExpectsOneTypeParam, kindStr)
|
||||
|
||||
proc semVarType(c: PContext, n: PNode, prev: PType): PType =
|
||||
var base: PType
|
||||
result = newOrPrevType(tyVar, prev, c)
|
||||
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)
|
||||
addSon(result, base)
|
||||
else:
|
||||
@@ -111,15 +108,14 @@ proc semDistinct(c: PContext, n: PNode, prev: PType): PType =
|
||||
else: liMessage(n.info, errXExpectsOneTypeParam, "distinct")
|
||||
|
||||
proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
|
||||
var a, b: PNode
|
||||
if (n.kind != nkRange): InternalError(n.info, "semRangeAux")
|
||||
checkSonsLen(n, 2)
|
||||
result = newOrPrevType(tyRange, prev, c)
|
||||
result.n = newNodeI(nkRange, n.info)
|
||||
if (n.sons[0] == nil) or (n.sons[1] == nil):
|
||||
liMessage(n.Info, errRangeIsEmpty)
|
||||
a = semConstExpr(c, n.sons[0])
|
||||
b = semConstExpr(c, n.sons[1])
|
||||
var a = semConstExpr(c, n.sons[0])
|
||||
var b = semConstExpr(c, n.sons[1])
|
||||
if not sameType(a.typ, b.typ): liMessage(n.info, errPureTypeMismatch)
|
||||
if not (a.typ.kind in
|
||||
{tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}):
|
||||
@@ -159,10 +155,9 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
liMessage(n.info, errArrayExpectsTwoTypeParams)
|
||||
|
||||
proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
|
||||
var base: PType
|
||||
result = newOrPrevType(tyOrdinal, prev, c)
|
||||
if sonsLen(n) == 2:
|
||||
base = semTypeNode(c, n.sons[1], nil)
|
||||
var base = semTypeNode(c, n.sons[1], nil)
|
||||
if base.kind != tyGenericParam:
|
||||
if not isOrdinalType(base):
|
||||
liMessage(n.sons[1].info, errOrdinalTypeExpected)
|
||||
@@ -231,7 +226,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
|
||||
allowed: TSymFlags): PSym =
|
||||
# identifier with visibility
|
||||
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)
|
||||
var v = n.sons[0].ident
|
||||
if (sfStar in allowed) and (v.id == ord(wStar)):
|
||||
@@ -426,7 +421,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
base: PType
|
||||
pos: int
|
||||
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)
|
||||
if n.sons[1] != 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,
|
||||
cl: var TIntSet): PType =
|
||||
var
|
||||
L: int
|
||||
s: PSym
|
||||
result = t
|
||||
if (t == nil): return
|
||||
if t == nil: return
|
||||
if IntSetContainsOrIncl(cl, t.id): return
|
||||
case t.kind
|
||||
of tyGenericBody:
|
||||
#debug(t)
|
||||
result = newTypeS(tyGenericInvokation, c)
|
||||
addSon(result, t)
|
||||
for i in countup(0, sonsLen(t) - 2):
|
||||
if t.sons[i].kind != tyGenericParam:
|
||||
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)
|
||||
addDecl(c, s)
|
||||
addSon(genericParams, newSymNode(s))
|
||||
addSon(result, t.sons[i])
|
||||
of tyGenericInst:
|
||||
L = sonsLen(t) - 1
|
||||
#debug(t)
|
||||
var L = sonsLen(t) - 1
|
||||
t.sons[L] = addTypeVarsOfGenericBody(c, t.sons[L], genericParams, cl)
|
||||
of tyGenericInvokation:
|
||||
#debug(t)
|
||||
for i in countup(1, sonsLen(t) - 1):
|
||||
t.sons[i] = addTypeVarsOfGenericBody(c, t.sons[i], genericParams, cl)
|
||||
else:
|
||||
@@ -476,13 +473,12 @@ proc paramType(c: PContext, n, genericParams: PNode, cl: var TIntSet): PType =
|
||||
result = semTypeNode(c, n, nil)
|
||||
if (genericParams != nil) and (sonsLen(genericParams) == 0):
|
||||
result = addTypeVarsOfGenericBody(c, result, genericParams, cl)
|
||||
#if result.kind == tyGenericInvokation: debug(result)
|
||||
|
||||
proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
|
||||
var
|
||||
length, counter: int
|
||||
a, def, res: PNode
|
||||
def, res: PNode
|
||||
typ: PType
|
||||
arg: PSym
|
||||
check, cl: TIntSet
|
||||
checkMinSonsLen(n, 1)
|
||||
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 n.sons[0] == nil:
|
||||
addSon(result, nil) # return type
|
||||
addSon(result.n, newNodeI(nkType, n.info)) # BUGFIX: nkType must exist!
|
||||
# XXX but it does not, if n.sons[paramsPos] == nil?
|
||||
addSon(result.n, newNodeI(nkType, n.info))
|
||||
# BUGFIX: nkType must exist!
|
||||
# XXX but it does not, if n.sons[paramsPos] == nil?
|
||||
else:
|
||||
addSon(result, nil)
|
||||
res = newNodeI(nkType, n.info)
|
||||
addSon(result.n, res)
|
||||
IntSetInit(check)
|
||||
counter = 0
|
||||
var counter = 0
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
a = n.sons[i]
|
||||
if (a.kind != nkIdentDefs): IllFormedAst(a)
|
||||
var a = n.sons[i]
|
||||
if a.kind != nkIdentDefs: IllFormedAst(a)
|
||||
checkMinSonsLen(a, 3)
|
||||
length = sonsLen(a)
|
||||
var length = sonsLen(a)
|
||||
if a.sons[length - 2] != nil:
|
||||
typ = paramType(c, a.sons[length - 2], genericParams, cl)
|
||||
else:
|
||||
typ = nil
|
||||
if a.sons[length - 1] != nil:
|
||||
def = semExprWithType(c, a.sons[length - 1]) # check type compability between def.typ and typ:
|
||||
if (typ != nil):
|
||||
if (cmpTypes(typ, def.typ) < isConvertible):
|
||||
def = semExprWithType(c, a.sons[length - 1])
|
||||
# check type compability between def.typ and typ:
|
||||
if typ != nil:
|
||||
if cmpTypes(typ, def.typ) < isConvertible:
|
||||
typeMismatch(a.sons[length - 1], typ, def.typ)
|
||||
def = fitNode(c, typ, def)
|
||||
else:
|
||||
@@ -519,7 +517,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
|
||||
else:
|
||||
def = nil
|
||||
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.position = counter
|
||||
inc(counter)
|
||||
@@ -600,21 +598,16 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
markUsed(n, n.sym)
|
||||
else:
|
||||
liMessage(n.info, errTypeExpected)
|
||||
of nkObjectTy:
|
||||
result = semObjectNode(c, n, prev)
|
||||
of nkTupleTy:
|
||||
result = semTuple(c, n, prev)
|
||||
of nkRefTy:
|
||||
result = semAnyRef(c, n, tyRef, "ref", 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 nkObjectTy: result = semObjectNode(c, n, prev)
|
||||
of nkTupleTy: result = semTuple(c, n, prev)
|
||||
of nkRefTy: result = semAnyRef(c, n, tyRef, "ref", 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:
|
||||
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.typ = result
|
||||
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) =
|
||||
case m.magic #registerSysType(m.typ);
|
||||
of mInt:
|
||||
setMagicType(m, tyInt, intSize)
|
||||
of mInt8:
|
||||
setMagicType(m, tyInt8, 1)
|
||||
of mInt16:
|
||||
setMagicType(m, tyInt16, 2)
|
||||
of mInt32:
|
||||
setMagicType(m, tyInt32, 4)
|
||||
of mInt64:
|
||||
setMagicType(m, tyInt64, 8)
|
||||
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 mInt: setMagicType(m, tyInt, intSize)
|
||||
of mInt8: setMagicType(m, tyInt8, 1)
|
||||
of mInt16: setMagicType(m, tyInt16, 2)
|
||||
of mInt32: setMagicType(m, tyInt32, 4)
|
||||
of mInt64: setMagicType(m, tyInt64, 8)
|
||||
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:
|
||||
setMagicType(m, tyString, ptrSize)
|
||||
addSon(m.typ, getSysType(tyChar))
|
||||
of mCstring:
|
||||
setMagicType(m, tyCString, ptrSize)
|
||||
addSon(m.typ, getSysType(tyChar))
|
||||
of mPointer:
|
||||
setMagicType(m, tyPointer, ptrSize)
|
||||
of mPointer: setMagicType(m, tyPointer, ptrSize)
|
||||
of mEmptySet:
|
||||
setMagicType(m, tySet, 1)
|
||||
addSon(m.typ, newTypeS(tyEmpty, c))
|
||||
of mIntSetBaseType:
|
||||
setMagicType(m, tyRange, intSize) #intSetBaseType := m.typ;
|
||||
return
|
||||
of mNil:
|
||||
setMagicType(m, tyNil, ptrSize)
|
||||
of mExpr:
|
||||
setMagicType(m, tyExpr, 0)
|
||||
of mStmt:
|
||||
setMagicType(m, tyStmt, 0)
|
||||
of mTypeDesc:
|
||||
setMagicType(m, tyTypeDesc, 0)
|
||||
of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal:
|
||||
return
|
||||
of mNil: setMagicType(m, tyNil, ptrSize)
|
||||
of mExpr: setMagicType(m, tyExpr, 0)
|
||||
of mStmt: setMagicType(m, tyStmt, 0)
|
||||
of mTypeDesc: setMagicType(m, tyTypeDesc, 0)
|
||||
of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: return
|
||||
else: liMessage(m.info, errTypeExpected)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ type
|
||||
TTypeRelation = enum # order is important!
|
||||
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.subtypeMatches = 0
|
||||
c.convMatches = 0
|
||||
@@ -38,11 +38,25 @@ proc initCandidate(c: var TCandidate, callee: PType) =
|
||||
c.genericMatches = 0
|
||||
c.state = csEmpty
|
||||
c.callee = callee
|
||||
c.calleeSym = nil
|
||||
c.call = nil
|
||||
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) =
|
||||
a.exactMatches = b.exactMatches
|
||||
a.subtypeMatches = b.subtypeMatches
|
||||
@@ -326,7 +340,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||
case a.kind
|
||||
of tyPointer: result = isEqual
|
||||
of tyNil: result = isSubtype
|
||||
of tyRef, tyPtr, tyProc, tyCString: result = isConvertible
|
||||
of tyPtr, tyProc, tyCString: result = isConvertible
|
||||
else: nil
|
||||
of tyString:
|
||||
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:
|
||||
result = true
|
||||
|
||||
proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode =
|
||||
var
|
||||
proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
|
||||
initialBinding: PNode): PNode =
|
||||
var
|
||||
o: TOverloadIter
|
||||
x, y, z: TCandidate
|
||||
#liMessage(n.info, warnUser, renderTree(n));
|
||||
var sym = initOverloadIter(o, c, n.sons[0])
|
||||
var sym = initOverloadIter(o, c, f)
|
||||
result = nil
|
||||
if sym == nil: return
|
||||
initCandidate(x, sym.typ)
|
||||
x.calleeSym = sym
|
||||
initCandidate(y, sym.typ)
|
||||
y.calleeSym = sym
|
||||
initCandidate(x, sym, initialBinding)
|
||||
initCandidate(y, sym, initialBinding)
|
||||
while sym != nil:
|
||||
if sym.kind in filter:
|
||||
initCandidate(z, sym.typ)
|
||||
initCandidate(z, sym, initialBinding)
|
||||
z.calleeSym = sym
|
||||
matches(c, n, z)
|
||||
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
|
||||
elif cmp == 0: y = z # z is as good as x
|
||||
else: nil
|
||||
sym = nextOverloadIter(o, c, n.sons[0])
|
||||
sym = nextOverloadIter(o, c, f)
|
||||
if x.state == csEmpty:
|
||||
# no overloaded proc found
|
||||
# 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.sons[0] = newSymNode(x.calleeSym)
|
||||
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)
|
||||
|
||||
proc transform(c: PTransf, n: PNode): PNode
|
||||
#
|
||||
#
|
||||
#Transforming iterators into non-inlined versions is pretty hard, but
|
||||
#unavoidable for not bloating the code too much. If we had direct access to
|
||||
#the program counter, things'd be much easier.
|
||||
#::
|
||||
#
|
||||
# iterator items(a: string): char =
|
||||
# var i = 0
|
||||
# while i < length(a):
|
||||
# yield a[i]
|
||||
# inc(i)
|
||||
#
|
||||
# for ch in items("hello world"): # `ch` is an iteration variable
|
||||
# echo(ch)
|
||||
#
|
||||
#Should be transformed into::
|
||||
#
|
||||
# type
|
||||
# TItemsClosure = record
|
||||
# i: int
|
||||
# state: int
|
||||
# proc items(a: string, c: var TItemsClosure): char =
|
||||
# case c.state
|
||||
# of 0: goto L0 # very difficult without goto!
|
||||
# of 1: goto L1 # can be implemented by GCC's computed gotos
|
||||
#
|
||||
# block L0:
|
||||
# c.i = 0
|
||||
# while c.i < length(a):
|
||||
# c.state = 1
|
||||
# return a[i]
|
||||
# block L1: inc(c.i)
|
||||
#
|
||||
#More efficient, but not implementable::
|
||||
#
|
||||
# type
|
||||
# TItemsClosure = record
|
||||
# i: int
|
||||
# pc: pointer
|
||||
#
|
||||
# proc items(a: string, c: var TItemsClosure): char =
|
||||
# goto c.pc
|
||||
# c.i = 0
|
||||
# while c.i < length(a):
|
||||
# c.pc = label1
|
||||
# return a[i]
|
||||
# label1: inc(c.i)
|
||||
#
|
||||
|
||||
# Transforming iterators into non-inlined versions is pretty hard, but
|
||||
# unavoidable for not bloating the code too much. If we had direct access to
|
||||
# the program counter, things'd be much easier.
|
||||
# ::
|
||||
#
|
||||
# iterator items(a: string): char =
|
||||
# var i = 0
|
||||
# while i < length(a):
|
||||
# yield a[i]
|
||||
# inc(i)
|
||||
#
|
||||
# for ch in items("hello world"): # `ch` is an iteration variable
|
||||
# echo(ch)
|
||||
#
|
||||
# Should be transformed into::
|
||||
#
|
||||
# type
|
||||
# TItemsClosure = record
|
||||
# i: int
|
||||
# state: int
|
||||
# proc items(a: string, c: var TItemsClosure): char =
|
||||
# case c.state
|
||||
# of 0: goto L0 # very difficult without goto!
|
||||
# of 1: goto L1 # can be implemented by GCC's computed gotos
|
||||
#
|
||||
# block L0:
|
||||
# c.i = 0
|
||||
# while c.i < length(a):
|
||||
# c.state = 1
|
||||
# return a[i]
|
||||
# block L1: inc(c.i)
|
||||
#
|
||||
# More efficient, but not implementable::
|
||||
#
|
||||
# type
|
||||
# TItemsClosure = record
|
||||
# i: int
|
||||
# pc: pointer
|
||||
#
|
||||
# proc items(a: string, c: var TItemsClosure): char =
|
||||
# goto c.pc
|
||||
# c.i = 0
|
||||
# while c.i < length(a):
|
||||
# c.pc = label1
|
||||
# return a[i]
|
||||
# label1: inc(c.i)
|
||||
#
|
||||
|
||||
proc newAsgnStmt(c: PTransf, le, ri: PNode): PNode =
|
||||
result = newNodeI(nkFastAsgn, ri.info)
|
||||
addSon(result, le)
|
||||
@@ -290,8 +290,8 @@ proc transformConv(c: PTransf, n: PNode): PNode =
|
||||
if not isOrdinalType(source):
|
||||
# XXX int64 -> float conversion?
|
||||
result = n
|
||||
elif (firstOrd(dest) <= firstOrd(source)) and
|
||||
(lastOrd(source) <= lastOrd(dest)):
|
||||
elif firstOrd(dest) <= firstOrd(source) and
|
||||
lastOrd(source) <= lastOrd(dest):
|
||||
# BUGFIX: simply leave n as it is; we need a nkConv node,
|
||||
# but no range check:
|
||||
result = n
|
||||
@@ -540,8 +540,8 @@ proc getMergeOp(n: PNode): PSym =
|
||||
|
||||
proc flattenTreeAux(d, a: PNode, op: PSym) =
|
||||
var op2 = getMergeOp(a)
|
||||
if (op2 != nil) and
|
||||
((op2.id == op.id) or (op.magic != mNone) and (op2.magic == op.magic)):
|
||||
if op2 != nil and
|
||||
(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)
|
||||
else:
|
||||
addSon(d, copyTree(a))
|
||||
|
||||
@@ -17,6 +17,7 @@ tcnstseq.nim;AngelikaAnneAnnaAnkaAnja
|
||||
tconstr2.nim;69
|
||||
tcopy.nim;TEMP=C:\Programs\xyz\bin
|
||||
tcurrncy.nim;25
|
||||
texplicitgeneric1.nim;Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13
|
||||
tfinally.nim;came here
|
||||
tfloat1.nim;Error: unhandled exception: FPU operation caused an overflow [EFloatOverflow]
|
||||
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
|
||||
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
|
||||
@@ -24,6 +31,10 @@ Additions
|
||||
|
||||
- The ``{.compile: "file.c".}`` pragma uses a CRC check to see if the file
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user