diff options
author | Araq <rumpf_a@web.de> | 2012-12-02 00:44:29 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-12-02 00:44:29 +0100 |
commit | 76885c754a8f51a0ea34f76dd0843b1949ac7fde (patch) | |
tree | dc3a951f7d7256567c4ea699fd359675143a7051 /compiler | |
parent | 9c0355a13fce08b99f2bac52d7042b73f21003d7 (diff) | |
download | Nim-76885c754a8f51a0ea34f76dd0843b1949ac7fde.tar.gz |
first version of ropes.nim with unsafeNew (broken)
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/ccgexprs.nim | 15 | ||||
-rw-r--r-- | compiler/ccgmerge.nim | 37 | ||||
-rwxr-xr-x | compiler/docgen.nim | 8 | ||||
-rwxr-xr-x | compiler/ropes.nim | 101 |
4 files changed, 101 insertions, 60 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 57d06a988..cb0dcfe00 100755 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -933,22 +933,31 @@ proc genNew(p: BProc, e: PNode) = var a, b: TLoc reftype, bt: PType + sizeExpr: PRope refType = skipTypes(e.sons[1].typ, abstractVarRange) InitLocExpr(p, e.sons[1], a) initLoc(b, locExpr, a.t, OnHeap) + # 'genNew' also handles 'unsafeNew': + if e.len == 3: + var se: TLoc + InitLocExpr(p, e.sons[2], se) + sizeExpr = se.rdLoc + else: + sizeExpr = ropef("sizeof($1)", + getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))) let args = [getTypeDesc(p.module, reftype), genTypeInfo(p.module, refType), - getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))] + sizeExpr] if a.s == OnHeap and optRefcGc in gGlobalOptions: # use newObjRC1 as an optimization; and we don't need 'keepAlive' either if canFormAcycle(a.t): lineCg(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc) else: lineCg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", a.rdLoc) - b.r = ropecg(p.module, "($1) #newObjRC1($2, sizeof($3))", args) + b.r = ropecg(p.module, "($1) #newObjRC1($2, $3)", args) lineCg(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc) else: - b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", args) + b.r = ropecg(p.module, "($1) #newObj($2, $3)", args) genAssignment(p, a, b, {needToKeepAlive}) # set the object type: bt = skipTypes(refType.sons[0], abstractRange) genObjectInit(p, cpsStmts, bt, a, false) diff --git a/compiler/ccgmerge.nim b/compiler/ccgmerge.nim index df7e7f68b..027cd5780 100644 --- a/compiler/ccgmerge.nim +++ b/compiler/ccgmerge.nim @@ -145,20 +145,47 @@ proc atEndMark(buf: cstring, pos: int): bool = while s < NimMergeEndMark.len and buf[pos+s] == NimMergeEndMark[s]: inc s result = s == NimMergeEndMark.len +when false: + proc readVerbatimSection(L: var TBaseLexer): PRope = + var pos = L.bufpos + var buf = L.buf + result = newMutableRope(30_000) + while true: + case buf[pos] + of CR: + pos = lexbase.HandleCR(L, pos) + buf = L.buf + result.data.add(tnl) + of LF: + pos = lexbase.HandleLF(L, pos) + buf = L.buf + result.data.add(tnl) + of '\0': + InternalError("ccgmerge: expected: " & NimMergeEndMark) + break + else: + if atEndMark(buf, pos): + inc pos, NimMergeEndMark.len + break + result.data.add(buf[pos]) + inc pos + L.bufpos = pos + freezeMutableRope(result) + proc readVerbatimSection(L: var TBaseLexer): PRope = var pos = L.bufpos var buf = L.buf - result = newMutableRope(30_000) + var r = newStringOfCap(30_000) while true: case buf[pos] of CR: pos = lexbase.HandleCR(L, pos) buf = L.buf - result.data.add(tnl) + r.add(tnl) of LF: pos = lexbase.HandleLF(L, pos) buf = L.buf - result.data.add(tnl) + r.add(tnl) of '\0': InternalError("ccgmerge: expected: " & NimMergeEndMark) break @@ -166,10 +193,10 @@ proc readVerbatimSection(L: var TBaseLexer): PRope = if atEndMark(buf, pos): inc pos, NimMergeEndMark.len break - result.data.add(buf[pos]) + r.add(buf[pos]) inc pos L.bufpos = pos - freezeMutableRope(result) + result = r.toRope proc readKey(L: var TBaseLexer, result: var string) = var pos = L.bufpos diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 5d46be874..e06277f91 100755 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -350,9 +350,11 @@ proc CommandRstAux(filename, outExt: string) = var d = newDocumentor(filen, options.gConfigVars) var rst = parseRst(readFile(filen), filen, 0, 1, d.hasToc, {roSupportRawDirective}) - d.modDesc = newMutableRope(30_000) - renderRstToOut(d[], rst, d.modDesc.data) - freezeMutableRope(d.modDesc) + var modDesc = newStringOfCap(30_000) + #d.modDesc = newMutableRope(30_000) + renderRstToOut(d[], rst, modDesc) + #freezeMutableRope(d.modDesc) + d.modDesc = toRope(modDesc) writeOutput(d, filename, outExt) generateIndex(d) diff --git a/compiler/ropes.nim b/compiler/ropes.nim index 50c89e4d9..af05c68a7 100755 --- a/compiler/ropes.nim +++ b/compiler/ropes.nim @@ -58,6 +58,9 @@ import msgs, strutils, platform, hashes, crc, options +const + PayloadSize = 64_000 # dummy size for range checking + type TFormatStr* = string # later we may change it to CString for better # performance of the code generator (assignments @@ -66,9 +69,9 @@ type PRope* = ref TRope TRope*{.acyclic.} = object of TObject # the empty rope is represented # by nil to safe space - left*, right*: PRope - length*: int - data*: string # != nil if a leaf + left, right: PRope + L: int # < 0 if a leaf + d: array [0..PayloadSize, char] # != nil if a leaf TRopeSeq* = seq[PRope] @@ -94,22 +97,31 @@ proc RopeInvariant*(r: PRope): bool proc ropeLen(a: PRope): int = if a == nil: result = 0 - else: result = a.length + else: result = a.L.abs -proc newRope(data: string = nil): PRope = - new(result) - if data != nil: - result.length = len(data) - result.data = data +proc newRope(data: string = nil): PRope = + if data != nil: + unsafeNew(result, sizeof(TRope)-PayloadSize+len(data)) + result.L = -len(data) + # copy including '\0': + copyMem(addr result.d, cstring(data), len(data)) + else: + unsafeNew(result, sizeof(TRope)-PayloadSize) + +proc eqContent(r: PRope, s: string): bool = + assert r.L < 0 + if -r.L == s.len: + result = equalMem(addr(r.d), cstring(s), s.len) -proc newMutableRope*(capacity = 30): PRope = - ## creates a new rope that supports direct modifications of the rope's - ## 'data' and 'length' fields. - new(result) - result.data = newStringOfCap(capacity) +when false: + proc newMutableRope*(capacity = 30): PRope = + ## creates a new rope that supports direct modifications of the rope's + ## 'data' and 'length' fields. + new(result) + result.data = newStringOfCap(capacity) -proc freezeMutableRope*(r: PRope) {.inline.} = - r.length = r.data.len + proc freezeMutableRope*(r: PRope) {.inline.} = + r.length = r.data.len var cache: array[0..2048*2 -1, PRope] @@ -130,7 +142,7 @@ proc RopeInvariant(r: PRope): bool = proc insertInCache(s: string): PRope = var h = hash(s) and high(cache) result = cache[h] - if isNil(result) or result.data != s: + if isNil(result) or not eqContent(result, s): result = newRope(s) cache[h] = result @@ -155,19 +167,19 @@ proc newRecRopeToStr(result: var string, resultLen: var int, r: PRope) = var stack = @[r] while len(stack) > 0: var it = pop(stack) - while it.data == nil: + while it.L >= 0: add(stack, it.right) it = it.left - assert(it.data != nil) - CopyMem(addr(result[resultLen]), addr(it.data[0]), it.length) - Inc(resultLen, it.length) + assert(it.L < 0) + CopyMem(addr(result[resultLen]), addr(it.d[0]), -it.L) + Inc(resultLen, -it.L) assert(resultLen <= len(result)) proc ropeToStr(p: PRope): string = if p == nil: result = "" - else: - result = newString(p.length) + else: + result = newString(p.L.abs) var resultLen = 0 newRecRopeToStr(result, resultLen, p) @@ -176,7 +188,7 @@ proc con(a, b: PRope): PRope = elif b == nil: result = a else: result = newRope() - result.length = a.length + b.length + result.L = a.L.abs + b.L.abs result.left = a result.right = b @@ -192,16 +204,16 @@ proc app(a: var PRope, b: PRope) = a = con(a, b) proc app(a: var PRope, b: string) = a = con(a, b) proc prepend(a: var PRope, b: PRope) = a = con(b, a) -proc writeRope*(f: TFile, c: PRope) = +proc writeRope*(f: TFile, c: PRope) = var stack = @[c] - while len(stack) > 0: + while len(stack) > 0: var it = pop(stack) - while it.data == nil: + while it.L >= 0: add(stack, it.right) it = it.left assert(it != nil) - assert(it.data != nil) - write(f, it.data) + assert(it.L < 0) + write(f, cstring(it.d), -it.L) proc WriteRope*(head: PRope, filename: string, useWarning = false) = var f: tfile @@ -261,14 +273,14 @@ const bufSize = 1024 # 1 KB is reasonable proc auxRopeEqualsFile(r: PRope, bin: var tfile, buf: Pointer): bool = - if r.data != nil: - if r.length > bufSize: + if r.L < 0: + if -r.L > bufSize: internalError("ropes: token too long") return - var readBytes = readBuffer(bin, buf, r.length) - result = readBytes == r.length and - equalMem(buf, addr(r.data[0]), r.length) # BUGFIX - else: + var readBytes = readBuffer(bin, buf, -r.L) + result = readBytes == -r.L and + equalMem(buf, addr(r.d[0]), readBytes) + else: result = auxRopeEqualsFile(r.left, bin, buf) if result: result = auxRopeEqualsFile(r.right, bin, buf) @@ -284,29 +296,20 @@ proc RopeEqualsFile(r: PRope, f: string): bool = dealloc(buf) close(bin) -proc crcFromRopeAux(r: PRope, startVal: TCrc32): TCrc32 = - if r.data != nil: - result = startVal - for i in countup(0, len(r.data) - 1): - result = updateCrc32(r.data[i], result) - else: - result = crcFromRopeAux(r.left, startVal) - result = crcFromRopeAux(r.right, result) - proc newCrcFromRopeAux(r: PRope, startVal: TCrc32): TCrc32 = # XXX profiling shows this is actually expensive var stack: TRopeSeq = @[r] result = startVal while len(stack) > 0: var it = pop(stack) - while it.data == nil: + while it.L >= 0: add(stack, it.right) it = it.left - assert(it.data != nil) + assert(it.L < 0) var i = 0 - var L = len(it.data) - while i < L: - result = updateCrc32(it.data[i], result) + var L = -it.L + while i < L: + result = updateCrc32(it.d[i], result) inc(i) proc crcFromRope(r: PRope): TCrc32 = |