diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2009-05-10 22:35:58 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2009-05-10 22:35:58 +0200 |
commit | c7e144f97810630d8ab4f396f299c6355fc93ba7 (patch) | |
tree | f013e592eb209b66d3b56401e8c96d58929d57b1 | |
parent | d54b333e7e3df82732b70cade2e4b8591e4c2572 (diff) | |
download | Nim-c7e144f97810630d8ab4f396f299c6355fc93ba7.tar.gz |
added missing files;change config for bug #374441
-rw-r--r-- | doc/tut1.txt | 8 | ||||
-rw-r--r-- | doc/tut2.txt | 4 | ||||
-rw-r--r-- | examples/statcsv.nim | 2 | ||||
-rw-r--r-- | lib/alloc.nim | 6 | ||||
-rw-r--r-- | lib/ansi_c.nim | 1 | ||||
-rw-r--r-- | lib/cellsets.nim | 196 | ||||
-rw-r--r-- | lib/mm.nim | 1 | ||||
-rw-r--r-- | nim/highlite.pas | 3 | ||||
-rw-r--r-- | nim/strutils.pas | 8 | ||||
-rw-r--r-- | pycompab.py | 103 | ||||
-rw-r--r-- | rod/nimrod.cfg | 7 |
11 files changed, 324 insertions, 15 deletions
diff --git a/doc/tut1.txt b/doc/tut1.txt index 58a56e8f1..237663cdc 100644 --- a/doc/tut1.txt +++ b/doc/tut1.txt @@ -522,7 +522,7 @@ Result variable --------------- A procedure that returns a value has an implicit ``result`` variable that represents the return value. A ``return`` statement with no expression is a -shorthand for ``return result``. So all tree code snippets are equivalent: +shorthand for ``return result``. So all three code snippets are equivalent: .. code-block:: nimrod return 42 @@ -556,7 +556,7 @@ caller, a ``var`` parameter can be used: In the example, ``res`` and ``remainder`` are `var parameters`. Var parameters can be modified by the procedure and the changes are -visible to the caller. +visible to the caller. Discard statement @@ -952,8 +952,8 @@ Operation Comment ``dec(x, n)`` decrements `x` by `n`; `n` is an integer ``succ(x)`` returns the successor of `x` ``succ(x, n)`` returns the `n`'th successor of `x` -``succ(x)`` returns the predecessor of `x` -``succ(x, n)`` returns the `n`'th predecessor of `x` +``prec(x)`` returns the predecessor of `x` +``pred(x, n)`` returns the `n`'th predecessor of `x` ----------------- -------------------------------------------------------- The ``inc dec succ pred`` operations can fail by raising an `EOutOfRange` or diff --git a/doc/tut2.txt b/doc/tut2.txt index 6d2fd3094..114039887 100644 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -34,7 +34,7 @@ While Nimrod's support for object oriented programming (OOP) is minimalistic, powerful OOP technics can be used. OOP is seen as *one* way to design a program, not *the only* way. Often a procedural approach leads to simpler and more efficient code. In particular, prefering aggregation over inheritance -often yields to a better design. +often results in a better design. Objects @@ -422,7 +422,7 @@ containers: else: var it = root while it != nil: - # compare the data items; uses the generic ``cmd`` proc + # compare the data items; uses the generic ``cmp`` proc # that works for any type that has a ``==`` and ``<`` operator var c = cmp(it.data, n.data) if c < 0: diff --git a/examples/statcsv.nim b/examples/statcsv.nim index 9c1ebd113..e2f272a21 100644 --- a/examples/statcsv.nim +++ b/examples/statcsv.nim @@ -6,7 +6,7 @@ import os, streams, parsecsv, strutils, math if paramCount() < 1: - quit("Usage: sumcsv filename[.csv]") + quit("Usage: statcsv filename[.csv]") var filename = appendFileExt(ParamStr(1), "csv") var s = newFileStream(filename, fmRead) diff --git a/lib/alloc.nim b/lib/alloc.nim index e4d828449..95feff854 100644 --- a/lib/alloc.nim +++ b/lib/alloc.nim @@ -493,6 +493,10 @@ proc rawDealloc(a: var TAllocator, p: pointer) = f.zeroField = 0 f.next = c.freeList c.freeList = f + when overwriteFree: + # set to 0xff to check for usage after free bugs: + c_memset(cast[pointer](cast[int](p) +% sizeof(TFreeCell)), -1'i32, + s -% sizeof(TFreeCell)) # check if it is not in the freeSmallChunks[s] list: if c.free < s: assert c notin a.freeSmallChunks[s div memAlign] @@ -506,6 +510,8 @@ proc rawDealloc(a: var TAllocator, p: pointer) = c.size = SmallChunkSize freeBigChunk(a, cast[PBigChunk](c)) else: + # set to 0xff to check for usage after free bugs: + when overwriteFree: c_memset(p, -1'i32, c.size -% bigChunkOverhead()) # free big chunk freeBigChunk(a, cast[PBigChunk](c)) diff --git a/lib/ansi_c.nim b/lib/ansi_c.nim index 81abd2a3e..f307fb9ab 100644 --- a/lib/ansi_c.nim +++ b/lib/ansi_c.nim @@ -15,6 +15,7 @@ proc c_strcmp(a, b: CString): cint {.nodecl, importc: "strcmp".} proc c_memcmp(a, b: CString, size: cint): cint {.nodecl, importc: "memcmp".} proc c_memcpy(a, b: CString, size: cint) {.nodecl, importc: "memcpy".} proc c_strlen(a: CString): cint {.nodecl, importc: "strlen".} +proc c_memset(p: pointer, value: cint, size: int) {.nodecl, importc: "memset".} type C_TextFile {.importc: "FILE", nodecl, final.} = object # empty record for diff --git a/lib/cellsets.nim b/lib/cellsets.nim new file mode 100644 index 000000000..0ce83864c --- /dev/null +++ b/lib/cellsets.nim @@ -0,0 +1,196 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2009 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# Efficient set of pointers for the GC (and repr) + +type + TCell {.pure.} = object + refcount: int # the refcount and some flags + typ: PNimType + when debugGC: + filename: cstring + line: int + + PCell = ptr TCell + + PPageDesc = ptr TPageDesc + TBitIndex = range[0..UnitsPerPage-1] + TPageDesc {.final, pure.} = object + next: PPageDesc # all nodes are connected with this pointer + key: TAddress # start address at bit 0 + bits: array[TBitIndex, int] # a bit vector + + PPageDescArray = ptr array[0..1000_000, PPageDesc] + TCellSet {.final, pure.} = object + counter, max: int + head: PPageDesc + data: PPageDescArray + + PCellArray = ptr array[0..100_000_000, PCell] + TCellSeq {.final, pure.} = object + len, cap: int + d: PCellArray + +# ------------------- cell set handling --------------------------------------- + +proc contains(s: TCellSeq, c: PCell): bool {.inline.} = + for i in 0 .. s.len-1: + if s.d[i] == c: return True + return False + +proc add(s: var TCellSeq, c: PCell) {.inline.} = + if s.len >= s.cap: + s.cap = s.cap * 3 div 2 + var d = cast[PCellArray](alloc(s.cap * sizeof(PCell))) + copyMem(d, s.d, s.len * sizeof(PCell)) + dealloc(s.d) + s.d = d + # XXX: realloc? + s.d[s.len] = c + inc(s.len) + +proc init(s: var TCellSeq, cap: int = 1024) = + s.len = 0 + s.cap = cap + s.d = cast[PCellArray](alloc0(cap * sizeof(PCell))) + +proc deinit(s: var TCellSeq) = + dealloc(s.d) + s.d = nil + s.len = 0 + s.cap = 0 + +const + InitCellSetSize = 1024 # must be a power of two! + +proc Init(s: var TCellSet) = + s.data = cast[PPageDescArray](alloc0(InitCellSetSize * sizeof(PPageDesc))) + s.max = InitCellSetSize-1 + s.counter = 0 + s.head = nil + +proc Deinit(s: var TCellSet) = + var it = s.head + while it != nil: + var n = it.next + dealloc(it) + it = n + s.head = nil # play it safe here + dealloc(s.data) + s.data = nil + s.counter = 0 + +proc nextTry(h, maxHash: int): int {.inline.} = + result = ((5*h) + 1) and maxHash + # For any initial h in range(maxHash), repeating that maxHash times + # generates each int in range(maxHash) exactly once (see any text on + # random-number generation for proof). + +proc CellSetGet(t: TCellSet, key: TAddress): PPageDesc = + var h = cast[int](key) and t.max + while t.data[h] != nil: + if t.data[h].key == key: return t.data[h] + h = nextTry(h, t.max) + return nil + +proc CellSetRawInsert(t: TCellSet, data: PPageDescArray, desc: PPageDesc) = + var h = cast[int](desc.key) and t.max + while data[h] != nil: + assert(data[h] != desc) + h = nextTry(h, t.max) + assert(data[h] == nil) + data[h] = desc + +proc CellSetEnlarge(t: var TCellSet) = + var oldMax = t.max + t.max = ((t.max+1)*2)-1 + var n = cast[PPageDescArray](alloc0((t.max + 1) * sizeof(PPageDesc))) + for i in 0 .. oldmax: + if t.data[i] != nil: + CellSetRawInsert(t, n, t.data[i]) + dealloc(t.data) + t.data = n + +proc CellSetPut(t: var TCellSet, key: TAddress): PPageDesc = + var h = cast[int](key) and t.max + while true: + var x = t.data[h] + if x == nil: break + if x.key == key: return x + h = nextTry(h, t.max) + + if ((t.max+1)*2 < t.counter*3) or ((t.max+1)-t.counter < 4): + CellSetEnlarge(t) + inc(t.counter) + h = cast[int](key) and t.max + while t.data[h] != nil: h = nextTry(h, t.max) + assert(t.data[h] == nil) + # the new page descriptor goes into result + result = cast[PPageDesc](alloc0(sizeof(TPageDesc))) + result.next = t.head + result.key = key + t.head = result + t.data[h] = result + +# ---------- slightly higher level procs -------------------------------------- + +proc contains(s: TCellSet, cell: PCell): bool = + var u = cast[TAddress](cell) + var t = CellSetGet(s, u shr PageShift) + if t != nil: + u = (u %% PageSize) /% MemAlign + result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0 + else: + result = false + +proc incl(s: var TCellSet, cell: PCell) {.noinline.} = + var u = cast[TAddress](cell) + var t = CellSetPut(s, u shr PageShift) + u = (u %% PageSize) /% MemAlign + t.bits[u shr IntShift] = t.bits[u shr IntShift] or (1 shl (u and IntMask)) + +proc excl(s: var TCellSet, cell: PCell) = + var u = cast[TAddress](cell) + var t = CellSetGet(s, u shr PageShift) + if t != nil: + u = (u %% PageSize) /% MemAlign + t.bits[u shr IntShift] = (t.bits[u shr IntShift] and + not (1 shl (u and IntMask))) + +proc containsOrIncl(s: var TCellSet, cell: PCell): bool = + var u = cast[TAddress](cell) + var t = CellSetGet(s, u shr PageShift) + if t != nil: + u = (u %% PageSize) /% MemAlign + result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0 + if not result: + t.bits[u shr IntShift] = t.bits[u shr IntShift] or + (1 shl (u and IntMask)) + else: + Incl(s, cell) + result = false + +iterator elements(t: TCellSet): PCell {.inline.} = + # while traversing it is forbidden to add pointers to the tree! + var r = t.head + while r != nil: + var i = 0 + while i <= high(r.bits): + var w = r.bits[i] # taking a copy of r.bits[i] here is correct, because + # modifying operations are not allowed during traversation + var j = 0 + while w != 0: # test all remaining bits for zero + if (w and 1) != 0: # the bit is set! + yield cast[PCell]((r.key shl PageShift) or + (i shl IntShift +% j) *% MemAlign) + inc(j) + w = w shr 1 + inc(i) + r = r.next + diff --git a/lib/mm.nim b/lib/mm.nim index 5f16f7304..3bfb8a689 100644 --- a/lib/mm.nim +++ b/lib/mm.nim @@ -23,6 +23,7 @@ const reallyOsDealloc = true coalescRight = true coalescLeft = true + overwriteFree = false type PPointer = ptr pointer diff --git a/nim/highlite.pas b/nim/highlite.pas index ad7a6f724..1867268d3 100644 --- a/nim/highlite.pas +++ b/nim/highlite.pas @@ -358,7 +358,8 @@ begin end end; g.len := pos - g.pos; - if (g.kind <> gtEof) and (g.len <= 0) then InternalError('nimNextToken'); + if (g.kind <> gtEof) and (g.len <= 0) then + InternalError('nimNextToken: ' + toString(g.buf)); g.pos := pos; end; diff --git a/nim/strutils.pas b/nim/strutils.pas index cd07105be..377d3abc6 100644 --- a/nim/strutils.pas +++ b/nim/strutils.pas @@ -1,7 +1,7 @@ // // // The Nimrod Compiler -// (c) Copyright 2008 Andreas Rumpf +// (c) Copyright 2009 Andreas Rumpf // // See the file "copying.txt", included in this // distribution, for details about the copyright. @@ -45,6 +45,7 @@ function toString(i: BiggestInt): string; overload; //function toString(i: int): string; overload; function ToStringF(const r: Real): string; overload; function ToString(b: Boolean): string; overload; +function ToString(b: PChar): string; overload; function IntToStr(i: BiggestInt; minChars: int): string; @@ -415,6 +416,11 @@ begin result := sysUtils.intToStr(i); end; +function ToString(b: PChar): string; overload; +begin + result := string(b); +end; + function normalize(const s: string): string; var i: int; diff --git a/pycompab.py b/pycompab.py new file mode 100644 index 000000000..3121856ef --- /dev/null +++ b/pycompab.py @@ -0,0 +1,103 @@ +""" Python compability library + + With careful and painful coding, compability from Python 1.5.2 up to 3.0 + is achieved. Don't try this at home. + + Copyright 2009, Andreas Rumpf +""" + +import sys + +python3 = sys.version[0] >= "3" +python26 = sys.version[:3] == "2.6" + +true, false = 0==0, 0==1 + +if python3: + sys.exit("This script does not yet work with Python 3.0") + +try: + from cStringIO import StringIO +except ImportError: + from io import StringIO + +if python3: + def replace(s, a, b): return s.replace(a, b) + def lower(s): return s.lower() + def join(a, s=""): return s.join(a) + def find(s, a): return s.find(a) + def split(s, a=None): return s.split(a) + def strip(s): return s.strip() + + def has_key(dic, key): return key in dic +else: + from string import replace, lower, join, find, split, strip + + def has_key(dic, key): return dic.has_key(key) + +if not python3 and not python26: + import md5 + def newMD5(): return md5.new() + def MD5update(obj, x): + return obj.update(x) +else: + import hashlib + def newMD5(): return hashlib.md5() + def MD5update(obj, x): + if python26: + return obj.update(x) + else: + return obj.update(bytes(x, "utf-8")) + +def mydigest(hasher): + result = "" + for c in hasher.digest(): + if python3: + x = hex(c)[2:] + else: + x = hex(ord(c))[2:] + if len(x) == 1: x = "0" + x + result = result + x + return result + +def Subs(frmt, *args, **substitution): + DIGITS = "0123456789" + LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + chars = DIGITS+LETTERS+"_" + d = substitution + a = args + result = [] + i = 0 + L = len(frmt) + while i < L: + if frmt[i] == '$': + i = i+1 + if frmt[i] == '$': + result.append('$') + i = i+1 + elif frmt[i] == '{': + i = i+1 + j = i + while frmt[i] != '}': i = i+1 + i = i+1 # skip } + x = frmt[j:i-1] + if x[0] in DIGITS: + result.append(str(a[int(x)-1])) + else: + result.append(str(d[x])) + elif frmt[i] in chars: + j = i + i = i+1 + while i < len(frmt) and frmt[i] in chars: i = i + 1 + x = frmt[j:i] + if x[0] in DIGITS: + result.append(str(a[int(x)-1])) + else: + result.append(str(d[x])) + else: + assert(false) + else: + result.append(frmt[i]) + i = i+1 + return join(result, "") + diff --git a/rod/nimrod.cfg b/rod/nimrod.cfg index 65bb92bc5..d0293a5dd 100644 --- a/rod/nimrod.cfg +++ b/rod/nimrod.cfg @@ -5,12 +5,7 @@ @if llvm_gcc or gcc: # GCC, LLVM and Visual C++ have a problem to optimize some modules. # This is really strange. - @if windows or macosX: - cgen.speed = "-O0" - @else: - cgen.speed = "-O1 -fno-strict-aliasing" - @end + cgen.speed = "-O0" @elif vcc: cgen.speed = "" @end - |