explicit types for generic routines

This commit is contained in:
Andreas Rumpf
2010-05-28 23:32:46 +02:00
parent e90665bff2
commit 6c20509121
25 changed files with 411 additions and 343 deletions

View File

@@ -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
============================

View File

@@ -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.

View File

@@ -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>`_

View File

@@ -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]

View File

@@ -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)

View File

@@ -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 ----------------------------------------------- */

View File

@@ -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:

View File

@@ -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 =

View File

@@ -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 =

View File

@@ -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"

View File

@@ -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

View File

@@ -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)

View File

@@ -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>".}

View File

@@ -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

View File

@@ -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

View File

@@ -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])])

View File

@@ -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})

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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))

View File

@@ -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]
1 tack.nim 125
17 tconstr2.nim 69
18 tcopy.nim TEMP=C:\Programs\xyz\bin
19 tcurrncy.nim 25
20 texplicitgeneric1.nim Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13
21 tfinally.nim came here
22 tfloat1.nim Error: unhandled exception: FPU operation caused an overflow [EFloatOverflow]
23 tfloat2.nim Error: unhandled exception: FPU operation caused a NaN result [EFloatInvalidOp]

View File

@@ -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