diff --git a/config/nimdoc.cfg b/config/nimdoc.cfg
index 1db1ad6cff..541eacced5 100755
--- a/config/nimdoc.cfg
+++ b/config/nimdoc.cfg
@@ -1,5 +1,5 @@
# This is the config file for the documentation generator.
-# (c) 2010 Andreas Rumpf
+# (c) 2011 Andreas Rumpf
# Feel free to edit the templates as you need.
split.item.toc = "20"
@@ -45,12 +45,16 @@ doc.body_toc = """
$tableofcontents
$moduledesc
+
Dependencies
+ $deps
$content
"""
doc.body_no_toc = """
$moduledesc
+Dependencies
+ $deps
$content
"""
diff --git a/config/nimdoc.tex.cfg b/config/nimdoc.tex.cfg
index 54a57e0fb4..2ec5f98cb4 100755
--- a/config/nimdoc.tex.cfg
+++ b/config/nimdoc.tex.cfg
@@ -1,6 +1,6 @@
# This is the config file for the documentation generator that produces TeX
# output.
-# (c) 2009 Andreas Rumpf
+# (c) 2011 Andreas Rumpf
# Feel free to edit the templates as you need.
split.item.toc = "20"
@@ -30,11 +30,17 @@ doc.toc = r"\tableofcontents \newpage"
doc.body_toc = """
$tableofcontents
$moduledesc
+
+Dependencies: $deps
+
$content
"""
doc.body_no_toc = """
$moduledesc
+
+Dependencies: $deps
+
$content
"""
diff --git a/doc/lib.txt b/doc/lib.txt
index 2bdcc2272a..47cd08caba 100644
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -34,6 +34,10 @@ Core
* `macros `_
Contains the AST API and documentation of Nimrod for writing macros.
+* `marshal `_
+ Contains procs for serialization and deseralization of arbitrary Nimrod
+ data structures.
+
String handling
---------------
diff --git a/lib/impure/graphics.nim b/lib/impure/graphics.nim
index b6e2c06777..e8b10d56bb 100755
--- a/lib/impure/graphics.nim
+++ b/lib/impure/graphics.nim
@@ -24,7 +24,7 @@ type
w, h: int
s: sdl.PSurface
- EGraphics* = object of EBase
+ EGraphics* = object of EIO
TFont {.pure, final.} = object
f: sdl_ttf.PFont
diff --git a/lib/pure/hashtabs.nim b/lib/pure/hashtabs.nim
deleted file mode 100755
index 68d19d63b9..0000000000
--- a/lib/pure/hashtabs.nim
+++ /dev/null
@@ -1,163 +0,0 @@
-#
-#
-# Nimrod's Runtime Library
-# (c) Copyright 2009 Andreas Rumpf
-#
-# See the file "copying.txt", included in this
-# distribution, for details about the copyright.
-#
-
-## The ``hashtabs`` module implements an efficient generic hash
-## table/dictionary data type.
-
-import
- hashes
-
-const
- growthFactor = 2
- startSize = 8
- sham = sizeof(THash)*8-2 # shift amount
- mask = 0b11 shl sham
- usedSlot = 0b10 shl sham
- delSlot = 0b01 shl sham
- emptySlot = 0
-
-type
- TTable*[TKey, TValue] = object
- counter: int
- data: seq[tuple[key: TKey, val: TValue, h: THash]]
-
-proc init*(t: var TTable, size = startSize) =
- t.counter = 0
- newSeq(t.data, size)
-
-proc markUsed(h: THash): THash {.inline.} =
- return h and not mask or usedSlot
-
-proc len*(t: TTable): int {.inline.} =
- ## returns the number of keys in `t`.
- result = t.counter
-
-proc mustRehash(length, counter: int): bool =
- assert(length > counter)
- result = (length * 2 < counter * 3) or (length - counter < 4)
-
-proc nextTry(h, maxHash: THash): THash {.inline.} =
- result = ((5 * h) + 1) and maxHash
-
-template eq(a, b: expr): expr = a == b
-
-proc rawGet(t: TTable, key: TKey, fullhash: THash): int =
- var h = fullhash and high(t.data)
- while (t.data[h].h and mask) != 0:
- # If it is a deleted entry, the comparison with ``markUsed(fullhash)``
- # fails, so there is no need to check for this explicitely.
- if t.data[h].h == markUsed(fullhash) and eq(t.data[h].key, key): return h
- h = nextTry(h, high(t.data))
- result = - 1
-
-proc `[]`*(t: TTable, key: TKey): TValue =
- ## retrieves the value at ``t[key]``. If `key` is not in `t`,
- ## `EInvalidValue` is raised.
- var index = rawGet(t, key, hash(key))
- if index >= 0: result = t.data[index].val
- else:
- var e: ref EInvalidValue
- new(e)
- e.msg = "invalid key: " & $key
- raise e
-
-proc hasKey*(t: TTable, key: TKey): bool =
- ## returns true iff `key` is in the table `t`.
- result = rawGet(t, key) >= 0
-
-proc rawInsert[TKey, TValue](
- data: var seq[tuple[key: TKey, val: TValue, h: THash]],
- tup: tuple[key: TKey, val: TValue, h: THash]) =
- var h = tup.h and high(data)
- while (data[h].h and mask) == usedSlot: h = nextTry(h, high(data))
- data[h] = tup
-
-proc enlarge(t: var TTable) =
- var n: seq[tuple[key: TKey, val: TValue, h: THash]]
- newSeq(n, len(t.data) * growthFactor)
- for i in 0..high(t.data):
- if (t.data[i].h and mask) == usedSlot: rawInsert(n, t.data[i])
- swap(t.data, n)
-
-proc `[]=`*(t: var TTable, key: TKey, val: TValue) =
- ## puts a (key, value)-pair into `t`.
- var fullhash = hash(key)
- var index = rawGet(t, key, fullhash)
- if index >= 0:
- t.data[index].val = val
- else:
- if mustRehash(len(t.data), t.counter): enlarge(t)
- rawInsert(t.data, (key, val, markUsed(fullhash)))
- inc(t.counter)
-
-proc add*(t: var TTable, key: TKey, val: TValue) =
- ## puts a (key, value)-pair into `t`, but does not check if key already
- ## exists.
- if mustRehash(len(t.data), t.counter): enlarge(t)
- rawInsert(t.data, (key, val, markUsed(hash(key))))
- inc(t.counter)
-
-proc del*(t: var TTable, key: TKey) =
- ## deletes a (key, val)-pair in `t`.
- var index = rawGet(t, key)
- if index >= 0:
- t.data[index].h = delSlot
-
-proc delAll*(t: var TTable, key: TKey) =
- ## deletes all (key, val)-pairs in `t`.
- while true:
- var index = rawGet(t, key)
- if index < 0: break
- t.data[index].h = delSlot
-
-iterator pairs*(t: TTable): tuple[key: TKey, value: TValue] =
- ## iterates over any (key, value) pair in the table `t`.
- for h in 0..high(t.data):
- if (t.data[h].h and mask) == usedSlot:
- yield (t.data[h].key, t.data[h].val)
-
-iterator keys*(t: TTable): TKey =
- ## iterate over any key in the table `t`. If key occurs multiple times, it
- ## is yielded multiple times.
- for h in 0..high(t.data):
- if (t.data[h].h and mask) == usedSlot:
- yield t.data[h].key
-
-iterator values*(t: TTable): TValue =
- ## iterate over any value in the table `t`.
- for h in 0..high(t.data):
- if (t.data[h].h and mask) == usedSlot:
- yield t.data[h].val
-
-iterator values*(t: TTable, key: TKey): TValue =
- ## iterate over any value associated with `key` in `t`.
- var fullhash = hash(key)
- var h = fullhash and high(t.data)
- while (t.data[h].h and mask) != 0:
- # If it is a deleted entry, the comparison with ``markUsed(fullhash)``
- # fails, so there is no need to check for this explicitely.
- if t.data[h].h == markUsed(fullhash) and eq(t.data[h].key, key):
- yield t.data[h].val
- h = nextTry(h, high(t.data))
-
-proc `$`*[KeyToStr=`$`, ValueToStr=`$`](t: TTable): string =
- ## turns the table into its string representation. `$` must be available
- ## for TKey and TValue for this to work.
- if t.len == 0:
- result = "{:}"
- else:
- result = "{"
- var i = 0
- for k, v in pairs(t):
- if i > 0: add(result, ", ")
- add(result, KeyToStr(k))
- add(result, ": ")
- add(result, ValueToStr(v))
- inc(i)
- add(result, "}")
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 9948e6c9bb..092d8e5c63 100755
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -52,13 +52,13 @@ type
headers: PStringTable,
body: string]
- EInvalidProtocol* = object of EBase ## exception that is raised when server
- ## does not conform to the implemented
- ## protocol
+ EInvalidProtocol* = object of ESynch ## exception that is raised when server
+ ## does not conform to the implemented
+ ## protocol
- EHttpRequestErr* = object of EBase ## Thrown in the ``getContent`` proc
- ## and ``postContent`` proc,
- ## when the server returns an error
+ EHttpRequestErr* = object of ESynch ## Thrown in the ``getContent`` proc
+ ## and ``postContent`` proc,
+ ## when the server returns an error
proc httpError(msg: string) =
var e: ref EInvalidProtocol
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index c32a82397f..134c4926ff 100755
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -498,7 +498,7 @@ type
of JArray:
elems*: seq[PJsonNode]
- EJsonParsingError* = object of EBase
+ EJsonParsingError* = object of EInvalidValue
proc raiseParseErr(p: TJsonParser, msg: string) =
raise newException(EJsonParsingError, errorMsgExpected(p, msg))
diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim
index 6df39f50b7..81c6a53c56 100755
--- a/lib/pure/logging.nim
+++ b/lib/pure/logging.nim
@@ -8,7 +8,7 @@
#
## This module implements a simple logger. It is based on the following design:
-## * Runtime log formating is a bug: Sooner or later ever log file is parsed.
+## * Runtime log formating is a bug: Sooner or later every log file is parsed.
## * Keep it simple: If this library does not fullfill your needs, write your
## own. Trying to support every logging feature just leads to bloat.
##
diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim
index 2109c273ad..31951e9669 100755
--- a/lib/pure/parsesql.nim
+++ b/lib/pure/parsesql.nim
@@ -536,7 +536,7 @@ type
nkEnumDef
type
- EInvalidSql* = object of EBase ## Invalid SQL encountered
+ EInvalidSql* = object of EInvalidValue ## Invalid SQL encountered
PSqlNode* = ref TSqlNode ## an SQL abstract syntax tree node
TSqlNode* = object ## an SQL abstract syntax tree node
case kind*: TSqlNodeKind ## kind of syntax tree
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index f09e8f3b90..4628a3ff91 100755
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -1344,7 +1344,8 @@ proc arrowIsNextTok(c: TPegLexer): bool =
# ----------------------------- parser ----------------------------------------
type
- EInvalidPeg* = object of EBase ## raised if an invalid PEG has been detected
+ EInvalidPeg* = object of EInvalidValue ## raised if an invalid
+ ## PEG has been detected
TPegParser = object of TPegLexer ## the PEG parser object
tok: TToken
nonterms: seq[PNonTerminal]
diff --git a/lib/pure/smtp.nim b/lib/pure/smtp.nim
index 3490822b9e..21afdf953d 100644
--- a/lib/pure/smtp.nim
+++ b/lib/pure/smtp.nim
@@ -48,7 +48,7 @@ type
msgOtherHeaders: PStringTable
msgBody: string
- EInvalidReply* = object of EBase
+ EInvalidReply* = object of EIO
proc debugSend(smtp: TSMTP, cmd: string) =
if smtp.debug:
diff --git a/lib/pure/variants.nim b/lib/pure/variants.nim
deleted file mode 100755
index 620cd7b99f..0000000000
--- a/lib/pure/variants.nim
+++ /dev/null
@@ -1,181 +0,0 @@
-#
-#
-# Nimrod's Runtime Library
-# (c) Copyright 2010 Andreas Rumpf
-#
-# See the file "copying.txt", included in this
-# distribution, for details about the copyright.
-#
-
-## This module implements Nimrod's support for the ``variant`` datatype.
-## `TVariant` shows how the flexibility of dynamic typing is achieved
-## within a static type system.
-
-type
- TVarType* = enum
- vtNone,
- vtBool,
- vtChar,
- vtEnum,
- vtInt,
- vtFloat,
- vtString,
- vtSet,
- vtSeq,
- vtDict
- TVariant* {.final.} = object of TObject
- case vtype: TVarType
- of vtNone: nil
- of vtBool, vtChar, vtEnum, vtInt: vint: int64
- of vtFloat: vfloat: float64
- of vtString: vstring: string
- of vtSet, vtSeq: q: seq[TVariant]
- of vtDict: d: seq[tuple[key, val: TVariant]]
-
-iterator objectFields*[T](x: T, skipInherited: bool): tuple[
- key: string, val: TVariant] {.magic: "ObjectFields"}
-
-proc `?`*(x: ordinal): TVariant =
- result.kind = vtEnum
- result.vint = x
-
-proc `?`*(x: biggestInt): TVariant =
- result.kind = vtInt
- result.vint = x
-
-proc `?`*(x: char): TVariant =
- result.kind = vtChar
- result.vint = ord(x)
-
-proc `?`*(x: bool): TVariant =
- result.kind = vtBool
- result.vint = ord(x)
-
-proc `?`*(x: biggestFloat): TVariant =
- result.kind = vtFloat
- result.vfloat = x
-
-proc `?`*(x: string): TVariant =
- result.kind = vtString
- result.vstring = x
-
-proc `?`*[T](x: openArray[T]): TVariant =
- result.kind = vtSeq
- newSeq(result.q, x.len)
- for i in 0..x.len-1: result.q[i] = <>x[i]
-
-proc `?`*[T](x: set[T]): TVariant =
- result.kind = vtSet
- result.q = @[]
- for a in items(x): result.q.add(<>a)
-
-proc `?`* [T: object](x: T): TVariant {.magic: "ToVariant".}
- ## this converts a value to a variant ("boxing")
-
-proc `><`*[T](v: TVariant, typ: T): T {.magic: "FromVariant".}
-
-?[?5, ?67, ?"hello"]
-myVar?int
-
-
-proc `==`* (x, y: TVariant): bool =
- if x.vtype == y.vtype:
- case x.vtype
- of vtNone: result = true
- of vtBool, vtChar, vtEnum, vtInt: result = x.vint == y.vint
- of vtFloat: result = x.vfloat == y.vfloat
- of vtString: result = x.vstring == y.vstring
- of vtSet:
- # complicated! We check that each a in x also occurs in y and that the
- # counts are identical:
- if x.q.len == y.q.len:
- for a in items(x.q):
- block inner:
- for b in items(y.q):
- if a == b: break inner
- return false
- result = true
- of vtSeq:
- if x.q.len == y.q.len:
- for i in 0..x.q.len-1:
- if x.q[i] != y.q[i]: return false
- result = true
- of vtDict:
- # it is an ordered dict:
- if x.d.len == y.d.len:
- for i in 0..x.d.len-1:
- if x.d[i].key != y.d[i].key: return false
- if x.d[i].val != y.d[i].val: return false
- result = true
-
-proc `[]`* (a, b: TVariant): TVariant =
- case a.vtype
- of vtSeq:
- if b.vtype in {vtBool, vtChar, vtEnum, vtInt}:
- result = a.q[b.vint]
- else:
- variantError()
- of vtDict:
- for i in 0..a.d.len-1:
- if a.d[i].key == b: return a.d[i].val
- if b.vtype in {vtBool, vtChar, vtEnum, vtInt}:
- result = a.d[b.vint].val
- variantError()
- else: variantError()
-
-proc `[]=`* (a, b, c: TVariant) =
- case a.vtype
- of vtSeq:
- if b.vtype in {vtBool, vtChar, vtEnum, vtInt}:
- a.q[b.vint] = b
- else:
- variantError()
- of vtDict:
- for i in 0..a.d.len-1:
- if a.d[i].key == b:
- a.d[i].val = c
- return
- if b.vtype in {vtBool, vtChar, vtEnum, vtInt}:
- a.d[b.vint].val = c
- variantError()
- else: variantError()
-
-proc `[]`* (a: TVariant, b: int): TVariant {.inline} = return a[?b]
-proc `[]`* (a: TVariant, b: string): TVariant {.inline} = return a[?b]
-proc `[]=`* (a: TVariant, b: int, c: TVariant) {.inline} = a[?b] = c
-proc `[]=`* (a: TVariant, b: string, c: TVariant) {.inline} = a[?b] = c
-
-proc `+`* (x, y: TVariant): TVariant =
- case x.vtype
- of vtBool, vtChar, vtEnum, vtInt:
- if y.vtype == x.vtype:
- result.vtype = x.vtype
- result.vint = x.vint + y.vint
- else:
- case y.vtype
- of vtBool, vtChar, vtEnum, vtInt:
-
-
-
- vint: int64
- of vtFloat: vfloat: float64
- of vtString: vstring: string
- of vtSet, vtSeq: q: seq[TVariant]
- of vtDict: d: seq[tuple[key, val: TVariant]]
-
-proc `-`* (x, y: TVariant): TVariant
-proc `*`* (x, y: TVariant): TVariant
-proc `/`* (x, y: TVariant): TVariant
-proc `div`* (x, y: TVariant): TVariant
-proc `mod`* (x, y: TVariant): TVariant
-proc `&`* (x, y: TVariant): TVariant
-proc `$`* (x: TVariant): string =
- # uses JS notation
-
-proc parseVariant*(s: string): TVariant
-proc `<`* (x, y: TVariant): bool
-proc `<=`* (x, y: TVariant): bool
-
-proc hash*(x: TVariant): int =
-
-
diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim
index b7ee165f51..552bd54cfc 100755
--- a/lib/pure/xmldom.nim
+++ b/lib/pure/xmldom.nim
@@ -16,7 +16,7 @@ import strutils
#Exceptions
type
- EDOMException* = object of E_Base ## Base exception object for all DOM Exceptions
+ EDOMException* = object of EInvalidValue ## Base exception object for all DOM Exceptions
EDOMStringSizeErr* = object of EDOMException ## If the specified range of text does not fit into a DOMString
## Currently not used(Since DOMString is just string)
EHierarchyRequestErr* = object of EDOMException ## If any node is inserted somewhere it doesn't belong
diff --git a/lib/pure/xmldomparser.nim b/lib/pure/xmldomparser.nim
index d9eb210c33..fda46bac0f 100755
--- a/lib/pure/xmldomparser.nim
+++ b/lib/pure/xmldomparser.nim
@@ -15,8 +15,8 @@ import xmldom, os, streams, parsexml, strutils
type
# Parsing errors
- EMismatchedTag* = object of E_Base ## Raised when a tag is not properly closed
- EParserError* = object of E_Base ## Raised when an unexpected XML Parser event occurs
+ EMismatchedTag* = object of EInvalidValue ## Raised when a tag is not properly closed
+ EParserError* = object of EInvalidValue ## Raised when an unexpected XML Parser event occurs
# For namespaces
xmlnsAttr = tuple[name, value: string, ownerElement: PElement]
diff --git a/lib/pure/xmlparser.nim b/lib/pure/xmlparser.nim
index 635497fa88..ad28bf6186 100755
--- a/lib/pure/xmlparser.nim
+++ b/lib/pure/xmlparser.nim
@@ -12,8 +12,9 @@
import streams, parsexml, strtabs, xmltree
type
- EInvalidXml* = object of E_Base ## exception that is raised for invalid XML
- errors*: seq[string] ## all detected parsing errors
+ EInvalidXml* = object of EInvalidValue ## exception that is raised
+ ## for invalid XML
+ errors*: seq[string] ## all detected parsing errors
proc raiseInvalidXml(errors: seq[string]) =
var e: ref EInvalidXml
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index 41efdf4311..6c54357244 100755
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -244,7 +244,7 @@ proc nimIntToStr(x: int): string {.compilerRtl.} =
proc nimFloatToStr(x: float): string {.compilerproc.} =
var buf: array [0..59, char]
- c_sprintf(buf, "%#g", x)
+ c_sprintf(buf, "%#.16e", x)
return $buf
proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
diff --git a/rod/docgen.nim b/rod/docgen.nim
index 7e141d633e..ade2aa93f5 100755
--- a/rod/docgen.nim
+++ b/rod/docgen.nim
@@ -32,7 +32,7 @@ type
filename*: string # filename of the source file; without extension
basedir*: string # base directory (where to put the documentation)
modDesc*: PRope # module description
- dependsOn*: PRope # dependencies
+ deps*: PRope # dependencies
id*: int # for generating IDs
splitAfter*: int # split too long entries in the TOC
tocPart*: seq[TTocEntry]
@@ -755,6 +755,19 @@ proc renderRstToOut(d: PDoc, n: PRstNode): PRope =
proc checkForFalse(n: PNode): bool =
result = n.kind == nkIdent and IdentEq(n.ident, "false")
+proc getModuleFile(n: PNode): string =
+ case n.kind
+ of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.strVal
+ of nkIdent: result = n.ident.s
+ of nkSym: result = n.sym.name.s
+ else:
+ internalError(n.info, "getModuleFile()")
+ result = ""
+
+proc traceDeps(d: PDoc, n: PNode) =
+ if d.deps != nil: app(d.deps, ", ")
+ app(d.deps, getModuleFile(n))
+
proc generateDoc(d: PDoc, n: PNode) =
if n == nil: return
case n.kind
@@ -783,6 +796,9 @@ proc generateDoc(d: PDoc, n: PNode) =
# generate documentation for the first branch only:
if not checkForFalse(n.sons[0].sons[0]):
generateDoc(d, lastSon(n.sons[0]))
+ of nkImportStmt:
+ for i in 0 .. sonsLen(n)-1: traceDeps(d, n.sons[i])
+ of nkFromStmt: traceDeps(d, n.sons[0])
else: nil
proc genSection(d: PDoc, kind: TSymKind) =
@@ -817,12 +833,14 @@ proc genOutFile(d: PDoc): PRope =
if d.hasToc: bodyname = "doc.body_toc"
else: bodyname = "doc.body_no_toc"
content = ropeFormatNamedVars(getConfigVar(bodyname), ["title",
- "tableofcontents", "moduledesc", "date", "time", "content"], [title, toc,
- d.modDesc, toRope(getDateStr()), toRope(getClockStr()), code])
- if not (optCompileOnly in gGlobalOptions):
+ "tableofcontents", "moduledesc", "deps", "date", "time", "content"],
+ [title, toc, d.modDesc, d.deps, toRope(getDateStr()),
+ toRope(getClockStr()), code])
+ if optCompileOnly notin gGlobalOptions:
code = ropeFormatNamedVars(getConfigVar("doc.file"), ["title",
- "tableofcontents", "moduledesc", "date", "time", "content", "author",
- "version"], [title, toc, d.modDesc, toRope(getDateStr()),
+ "tableofcontents", "moduledesc", "deps", "date", "time",
+ "content", "author", "version"],
+ [title, toc, d.modDesc, d.deps, toRope(getDateStr()),
toRope(getClockStr()), content, d.meta[metaAuthor],
d.meta[metaVersion]])
else: