diff options
-rwxr-xr-x | doc/intern.txt | 130 | ||||
-rwxr-xr-x | doc/lib.txt | 2 | ||||
-rwxr-xr-x | doc/theindex.txt | 138 | ||||
-rwxr-xr-x | examples/keyval.nim | 4 | ||||
-rwxr-xr-x | lib/impure/dialogs.nim | 5 | ||||
-rwxr-xr-x | lib/nimbase.h | 7 | ||||
-rwxr-xr-x | lib/pure/os.nim | 7 | ||||
-rwxr-xr-x | lib/pure/times.nim | 27 | ||||
-rwxr-xr-x | lib/pure/unicode.nim | 2 | ||||
-rwxr-xr-x | lib/system.nim | 15 | ||||
-rwxr-xr-x | lib/system/alloc.nim | 8 | ||||
-rwxr-xr-x | lib/system/gc.nim | 7 | ||||
-rwxr-xr-x | lib/system/sysio.nim | 11 | ||||
-rwxr-xr-x | lib/wrappers/sdl/sdl.nim | 2 | ||||
-rwxr-xr-x | lib/wrappers/sdl/sdl_ttf.nim | 2 | ||||
-rwxr-xr-x | rod/docgen.nim | 11 | ||||
-rwxr-xr-x | rod/evals.nim | 3 | ||||
-rwxr-xr-x | rod/semexprs.nim | 2 | ||||
-rwxr-xr-x | rod/seminst.nim | 59 | ||||
-rwxr-xr-x | rod/semstmts.nim | 5 | ||||
-rwxr-xr-x | rod/semtypes.nim | 135 | ||||
-rwxr-xr-x | rod/sigmatch.nim | 54 | ||||
-rwxr-xr-x | rod/transf.nim | 106 | ||||
-rwxr-xr-x | tests/accept/run/spec.csv | 1 | ||||
-rwxr-xr-x | web/news.txt | 11 |
25 files changed, 411 insertions, 343 deletions
diff --git a/doc/intern.txt b/doc/intern.txt index 37c376568..50fc9b8b1 100755 --- a/doc/intern.txt +++ b/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 ============================ diff --git a/doc/lib.txt b/doc/lib.txt index a56aa5bf4..227a73405 100755 --- a/doc/lib.txt +++ b/doc/lib.txt @@ -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. diff --git a/doc/theindex.txt b/doc/theindex.txt index b734046af..9fc9b10e2 100755 --- a/doc/theindex.txt +++ b/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>`_ diff --git a/examples/keyval.nim b/examples/keyval.nim index f5ff4ac01..19a430a1e 100755 --- a/examples/keyval.nim +++ b/examples/keyval.nim @@ -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] diff --git a/lib/impure/dialogs.nim b/lib/impure/dialogs.nim index ef52d573a..c0b077177 100755 --- a/lib/impure/dialogs.nim +++ b/lib/impure/dialogs.nim @@ -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) diff --git a/lib/nimbase.h b/lib/nimbase.h index c7b3e551d..4c549120c 100755 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -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 ----------------------------------------------- */ diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 129774f6e..39ff699bb 100755 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -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: diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 70cb038a7..da712263d 100755 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -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 = diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index 099509afe..a43f66fa0 100755 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -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 = + diff --git a/lib/system.nim b/lib/system.nim index a83812ed0..b34adf62a 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -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" diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 95feff854..0d3f52b2f 100755 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -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 diff --git a/lib/system/gc.nim b/lib/system/gc.nim index da8f75768..1e9cd5a4a 100755 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -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) diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index 3c99a5eed..1dcc2ab3a 100755 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -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>".} diff --git a/lib/wrappers/sdl/sdl.nim b/lib/wrappers/sdl/sdl.nim index a4c8273b8..9b3f960b6 100755 --- a/lib/wrappers/sdl/sdl.nim +++ b/lib/wrappers/sdl/sdl.nim @@ -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 diff --git a/lib/wrappers/sdl/sdl_ttf.nim b/lib/wrappers/sdl/sdl_ttf.nim index ca4b56f5a..dd65af275 100755 --- a/lib/wrappers/sdl/sdl_ttf.nim +++ b/lib/wrappers/sdl/sdl_ttf.nim @@ -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 diff --git a/rod/docgen.nim b/rod/docgen.nim index 10516bf73..9da191d8d 100755 --- a/rod/docgen.nim +++ b/rod/docgen.nim @@ -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])]) diff --git a/rod/evals.nim b/rod/evals.nim index 7306f61b1..4232bb832 100755 --- a/rod/evals.nim +++ b/rod/evals.nim @@ -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}) diff --git a/rod/semexprs.nim b/rod/semexprs.nim index 8d8b627eb..6ce1628d5 100755 --- a/rod/semexprs.nim +++ b/rod/semexprs.nim @@ -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) diff --git a/rod/seminst.nim b/rod/seminst.nim index ba1f05cb2..417922825 100755 --- a/rod/seminst.nim +++ b/rod/seminst.nim @@ -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 diff --git a/rod/semstmts.nim b/rod/semstmts.nim index b07e724bc..0f96e5b94 100755 --- a/rod/semstmts.nim +++ b/rod/semstmts.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 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 diff --git a/rod/semtypes.nim b/rod/semtypes.nim index f4b17f071..a88490ce0 100755 --- a/rod/semtypes.nim +++ b/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) diff --git a/rod/sigmatch.nim b/rod/sigmatch.nim index 0698bf18d..a1b322d86 100755 --- a/rod/sigmatch.nim +++ b/rod/sigmatch.nim @@ -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) + diff --git a/rod/transf.nim b/rod/transf.nim index ac746f834..16c279c80 100755 --- a/rod/transf.nim +++ b/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)) diff --git a/tests/accept/run/spec.csv b/tests/accept/run/spec.csv index d537c139f..f176b5645 100755 --- a/tests/accept/run/spec.csv +++ b/tests/accept/run/spec.csv @@ -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] diff --git a/web/news.txt b/web/news.txt index 94ba076b7..7de119d34 100755 --- a/web/news.txt +++ b/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 |