diff options
43 files changed, 265 insertions, 180 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index fa7880c30..d1c10168a 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -337,7 +337,9 @@ type mFields, mFieldPairs, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, mAssert, - mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, mNewString, mReset, + mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, + mNewString, mNewStringOfCap, + mReset, mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal, mInt, mInt8, mInt16, mInt32, mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, mString, mCstring, diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 49afc3088..69c06fbb5 100755 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1457,7 +1457,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet, mInSet: genSetOp(p, e, d, op) - of mNewString, mCopyStr, mCopyStrLast, mExit: genCall(p, e, d) + of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit: + genCall(p, e, d) of mReset: genReset(p, e) of mEcho: genEcho(p, e) of mArrToSeq: genArrToSeq(p, e, d) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 619caf250..61cd36c42 100755 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -210,7 +210,7 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: openarray[PRope]): PRope = inc(i) var j = i while frmt[j] in IdentChars: inc(j) - var ident = copy(frmt, i, j-1) + var ident = substr(frmt, i, j-1) i = j app(result, cgsym(m, ident)) elif frmt[i] == '#' and frmt[i+1] == '$': @@ -225,7 +225,7 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: openarray[PRope]): PRope = if frmt[i] != '$' and frmt[i] != '#': inc(i) else: break if i - 1 >= start: - app(result, copy(frmt, start, i - 1)) + app(result, substr(frmt, start, i - 1)) proc appcg(m: BModule, c: var PRope, frmt: TFormatStr, args: openarray[PRope]) = @@ -489,9 +489,9 @@ proc libCandidates(s: string, dest: var TStringSeq) = var le = strutils.find(s, '(') var ri = strutils.find(s, ')', le+1) if le >= 0 and ri > le: - var prefix = copy(s, 0, le - 1) - var suffix = copy(s, ri + 1) - for middle in split(copy(s, le + 1, ri - 1), '|'): + var prefix = substr(s, 0, le - 1) + var suffix = substr(s, ri + 1) + for middle in split(substr(s, le + 1, ri - 1), '|'): libCandidates(prefix & middle & suffix, dest) else: add(dest, s) diff --git a/compiler/commands.nim b/compiler/commands.nim index d3eaf94a9..a4763d6b2 100755 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -172,7 +172,7 @@ proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass, else: break inc(i) if i >= len(switch): arg = "" - elif switch[i] in {':', '=', '['}: arg = copy(switch, i + 1) + elif switch[i] in {':', '=', '['}: arg = substr(switch, i + 1) else: InvalidCmdLineOption(pass, switch, info) proc ProcessOnOffSwitch(op: TOptions, arg: string, pass: TCmdlinePass, @@ -215,7 +215,7 @@ proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass, var x = findStr(msgs.WarningsToStr, id) if x >= 0: n = TNoteKind(x + ord(warnMin)) else: InvalidCmdLineOption(pass, arg, info) - case whichKeyword(copy(arg, i)) + case whichKeyword(substr(arg, i)) of wOn: incl(gNotes, n) of wOff: excl(gNotes, n) else: LocalError(info, errOnOrOffExpectedButXFound, arg) diff --git a/compiler/docgen.nim b/compiler/docgen.nim index eeb40f256..64973cddd 100755 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -156,7 +156,7 @@ proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openarray[string], while i < L: if (frmt[i] != '$'): inc(i) else: break - if i - 1 >= start: app(result, copy(frmt, start, i - 1)) + if i - 1 >= start: app(result, substr(frmt, start, i - 1)) proc addXmlChar(dest: var string, c: Char) = case c @@ -581,10 +581,10 @@ proc renderCodeBlock(d: PDoc, n: PRstNode): PRope = case g.kind of gtEof: break of gtNone, gtWhitespace: - app(result, copy(m.text, g.start + 0, g.length + g.start - 1 + 0)) + app(result, substr(m.text, g.start + 0, g.length + g.start - 1)) else: dispA(result, "<span class=\"$2\">$1</span>", "\\span$2{$1}", [ - toRope(esc(copy(m.text, g.start + 0, g.length + g.start - 1 + 0))), + toRope(esc(substr(m.text, g.start + 0, g.length + g.start - 1))), toRope(tokenClassToStr[g.kind])]) deinitGeneralTokenizer(g) if result != nil: diff --git a/compiler/evals.nim b/compiler/evals.nim index 20d2a68be..6fcbd911a 100755 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -990,7 +990,13 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode = var a = result result = newNodeIT(nkStrLit, n.info, n.typ) result.strVal = newString(int(getOrdValue(a))) - else: + of mNewStringOfCap: + result = evalAux(c, n.sons[1], {}) + if isSpecial(result): return + var a = result + result = newNodeIT(nkStrLit, n.info, n.typ) + result.strVal = newString(0) + else: result = evalAux(c, n.sons[1], {}) if isSpecial(result): return var a = result diff --git a/compiler/filter_tmpl.nim b/compiler/filter_tmpl.nim index 0bb402874..e56a08552 100755 --- a/compiler/filter_tmpl.nim +++ b/compiler/filter_tmpl.nim @@ -93,14 +93,14 @@ proc parseLine(p: var TTmplParser) = of wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator, wConverter, wMacro, wTemplate, wMethod: LLStreamWrite(p.outp, repeatChar(p.indent)) - LLStreamWrite(p.outp, copy(p.x, d)) + LLStreamWrite(p.outp, substr(p.x, d)) inc(p.indent, 2) of wElif, wOf, wElse, wExcept, wFinally: LLStreamWrite(p.outp, repeatChar(p.indent - 2)) - LLStreamWrite(p.outp, copy(p.x, d)) + LLStreamWrite(p.outp, substr(p.x, d)) else: LLStreamWrite(p.outp, repeatChar(p.indent)) - LLStreamWrite(p.outp, copy(p.x, d)) + LLStreamWrite(p.outp, substr(p.x, d)) p.state = psDirective else: # data line diff --git a/compiler/llstream.nim b/compiler/llstream.nim index 8dfa1e78e..2da56bccd 100755 --- a/compiler/llstream.nim +++ b/compiler/llstream.nim @@ -216,7 +216,7 @@ proc LLStreamReadAll(s: PLLStream): string = result = "" of llsString: if s.rd == 0: result = s.s - else: result = copy(s.s, s.rd + 0) + else: result = substr(s.s, s.rd) s.rd = len(s.s) of llsFile: result = newString(bufSize) diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim index d9580d955..e4a9d8827 100755 --- a/compiler/nimrod.nim +++ b/compiler/nimrod.nim @@ -33,8 +33,8 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) = # we fix this here var bracketLe = strutils.find(p.key, '[') if bracketLe >= 0: - var key = copy(p.key, 0, bracketLe - 1) - var val = copy(p.key, bracketLe + 1) & ':' & p.val + var key = substr(p.key, 0, bracketLe - 1) + var val = substr(p.key, bracketLe + 1) & ':' & p.val ProcessSwitch(key, val, pass, cmdLineInfo) else: ProcessSwitch(p.key, p.val, pass, cmdLineInfo) diff --git a/compiler/nstrtabs.nim b/compiler/nstrtabs.nim index 811e461cc..cd30887c5 100755 --- a/compiler/nstrtabs.nim +++ b/compiler/nstrtabs.nim @@ -153,13 +153,13 @@ proc `%`(f: string, t: PStringTable, flags: TFormatFlags = {}): string = of '{': var j = i + 1 while (j <= len(f) + 0 - 1) and (f[j] != '}'): inc(j) - var key = copy(f, i + 2 + 0 - 1, j - 1 + 0 - 1) + var key = substr(f, i + 2 + 0 - 1, j - 1 + 0 - 1) add(result, getValue(t, flags, key)) i = j + 1 of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_': var j = i + 1 while (j <= len(f) + 0 - 1) and (f[j] in PatternChars): inc(j) - var key = copy(f, i + 1 + 0 - 1, j - 1 + 0 - 1) + var key = substr(f, i + 1 + 0 - 1, j - 1 + 0 - 1) add(result, getValue(t, flags, key)) i = j else: @@ -168,4 +168,4 @@ proc `%`(f: string, t: PStringTable, flags: TFormatFlags = {}): string = else: add(result, f[i]) inc(i) - \ No newline at end of file + diff --git a/compiler/options.nim b/compiler/options.nim index 9dec04475..b4ee8cf67 100755 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -138,19 +138,19 @@ proc shortenDir(dir: string): string = # returns the interesting part of a dir var prefix = getPrefixDir() & dirSep if startsWith(dir, prefix): - return copy(dir, len(prefix)) + return substr(dir, len(prefix)) prefix = getCurrentDir() & dirSep if startsWith(dir, prefix): - return copy(dir, len(prefix)) + return substr(dir, len(prefix)) prefix = projectPath & dirSep #writeln(output, prefix); #writeln(output, dir); if startsWith(dir, prefix): - return copy(dir, len(prefix)) + return substr(dir, len(prefix)) result = dir proc removeTrailingDirSep*(path: string): string = if (len(path) > 0) and (path[len(path) - 1] == dirSep): - result = copy(path, 0, len(path) - 2) + result = substr(path, 0, len(path) - 2) else: result = path diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index c94b8b68b..7c78570e2 100755 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -119,7 +119,7 @@ proc processMagic(c: PContext, n: PNode, s: PSym) = # treat them as imported, instead of modifing a lot of working code # BUGFIX: magic does not imply ``lfNoDecl`` anymore! for m in countup(low(TMagic), high(TMagic)): - if copy($m, 1) == v: + if substr($m, 1) == v: s.magic = m return Message(n.info, warnUnknownMagic, v) @@ -333,12 +333,12 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode = var a = 0 while true: var b = strutils.find(str, marker, a) - var sub = if b < 0: copy(str, a) else: copy(str, a, b - 1) + var sub = if b < 0: substr(str, a) else: substr(str, a, b - 1) if sub != "": addSon(result, newStrNode(nkStrLit, sub)) if b < 0: break var c = strutils.find(str, marker, b + 1) - if c < 0: sub = copy(str, b + 1) - else: sub = copy(str, b + 1, c - 1) + if c < 0: sub = substr(str, b + 1) + else: sub = substr(str, b + 1, c - 1) if sub != "": var e = SymtabGet(con.tab, getIdent(sub)) if e != nil: diff --git a/compiler/renderer.nim b/compiler/renderer.nim index 2167c8e5d..3ee8450b2 100755 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -1106,7 +1106,7 @@ proc getNextTok(r: var TSrcGen, kind: var TTokType, literal: var string) = if r.idx < len(r.tokens): kind = r.tokens[r.idx].kind var length = r.tokens[r.idx].length - literal = copy(r.buf, r.pos + 0, r.pos + 0 + length - 1) + literal = substr(r.buf, r.pos + 0, r.pos + 0 + length - 1) inc(r.pos, length) inc(r.idx) else: diff --git a/compiler/ropes.nim b/compiler/ropes.nim index 9c4c5e700..01ca5c81e 100755 --- a/compiler/ropes.nim +++ b/compiler/ropes.nim @@ -328,7 +328,7 @@ proc ropef(frmt: TFormatStr, args: openarray[PRope]): PRope = if (frmt[i] != '$'): inc(i) else: break if i - 1 >= start: - app(result, copy(frmt, start, i - 1)) + app(result, substr(frmt, start, i - 1)) assert(RopeInvariant(result)) proc appf(c: var PRope, frmt: TFormatStr, args: openarray[PRope]) = diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 878c0a1a6..dbd5d34e5 100755 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -189,9 +189,9 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode = of mBoolToStr: if getOrdValue(a) == 0: result = newStrNodeT("false", n) else: result = newStrNodeT("true", n) - of mCopyStr: result = newStrNodeT(copy(getStr(a), int(getOrdValue(b))), n) + of mCopyStr: result = newStrNodeT(substr(getStr(a), int(getOrdValue(b))), n) of mCopyStrLast: - result = newStrNodeT(copy(getStr(a), int(getOrdValue(b)), + result = newStrNodeT(substr(getStr(a), int(getOrdValue(b)), int(getOrdValue(c))), n) of mFloatToStr: result = newStrNodeT($(getFloat(a)), n) of mCStrToStr, mCharToStr: result = newStrNodeT(getStrOrChar(a), n) @@ -205,7 +205,8 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode = of mCompileOptionArg: result = newIntNodeT(Ord( testCompileOptionArg(getStr(a), getStr(b), n.info)), n) - of mNewString, mExit, mInc, ast.mDec, mEcho, mAssert, mSwap, mAppendStrCh, + of mNewString, mNewStringOfCap, + mExit, mInc, ast.mDec, mEcho, mAssert, mSwap, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq, mNLen..mNError, mEqRef: nil diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index d5b8f3204..5b397167a 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -14,7 +14,7 @@ import ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst, magicsys -type +type TCandidateState* = enum csEmpty, csMatch, csNoMatch TCandidate* {.final.} = object @@ -33,7 +33,6 @@ type TTypeRelation* = enum # order is important! isNone, isConvertible, isIntConv, isSubtype, - isLifted, # match, but do not change argument type to formal's type! isGeneric, isEqual @@ -185,9 +184,6 @@ proc tupleRel(mapping: var TIdTable, f, a: PType): TTypeRelation = var x = f.n.sons[i].sym var y = a.n.sons[i].sym if x.name.id != y.name.id: return isNone - elif sonsLen(f) == 0: - idTablePut(mapping, f, a) - result = isLifted proc constraintRel(mapping: var TIdTable, f, a: PType): TTypeRelation = result = isNone @@ -226,7 +222,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation = of tyFloat64: result = handleFloatRange(f, a) of tyFloat128: result = handleFloatRange(f, a) of tyVar: - if (a.kind == f.kind): result = typeRel(mapping, base(f), base(a)) + if a.kind == f.kind: result = typeRel(mapping, base(f), base(a)) else: result = typeRel(mapping, base(f), a) of tyArray, tyArrayConstr: # tyArrayConstr cannot happen really, but @@ -493,9 +489,6 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType, of isSubtype: inc(m.subtypeMatches) result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c) - of isLifted: - inc(m.genericMatches) - result = copyTree(arg) of isGeneric: inc(m.genericMatches) result = copyTree(arg) diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim index b098e4817..14f7d7f03 100755 --- a/compiler/syntaxes.nim +++ b/compiler/syntaxes.nim @@ -98,7 +98,7 @@ proc parsePipe(filename: string, inputStream: PLLStream): PNode = inc(i, 2) while line[i] in WhiteSpace: inc(i) var q: TParser - OpenParser(q, filename, LLStreamOpen(copy(line, i))) + OpenParser(q, filename, LLStreamOpen(substr(line, i))) result = parser.parseAll(q) CloseParser(q) LLStreamClose(s) diff --git a/doc/apis.txt b/doc/apis.txt index 2932c05a9..260ce159b 100755 --- a/doc/apis.txt +++ b/doc/apis.txt @@ -32,6 +32,7 @@ get get, ``[]`` consider overloading ``[]`` for get; prefix: ``len`` instead of ``getLen`` length len also used for *number of elements* size size, len size should refer to a byte size +capacity cap memory mem implies a low-level operation items items default iterator over a collection pairs pairs iterator over (key, value) pairs @@ -69,6 +70,7 @@ coordinate coord rectangle rect point point symbol sym +string str identifier ident indentation indent ------------------- ------------ -------------------------------------- diff --git a/lib/impure/re.nim b/lib/impure/re.nim index 36adf5d1f..ccc13248a 100755 --- a/lib/impure/re.nim +++ b/lib/impure/re.nim @@ -88,7 +88,7 @@ proc matchOrFind(s: string, pattern: TRegEx, matches: var openarray[string], for i in 1..int(res)-1: var a = rawMatches[i * 2] var b = rawMatches[i * 2 + 1] - if a >= 0'i32: matches[i-1] = copy(s, int(a), int(b)-1) + if a >= 0'i32: matches[i-1] = substr(s, int(a), int(b)-1) else: matches[i-1] = "" return rawMatches[1] - rawMatches[0] @@ -106,7 +106,7 @@ proc findBounds*(s: string, pattern: TRegEx, matches: var openarray[string], for i in 1..int(res)-1: var a = rawMatches[i * 2] var b = rawMatches[i * 2 + 1] - if a >= 0'i32: matches[i-1] = copy(s, int(a), int(b)-1) + if a >= 0'i32: matches[i-1] = substr(s, int(a), int(b)-1) else: matches[i-1] = "" return (rawMatches[0].int, rawMatches[1].int - 1) @@ -186,7 +186,7 @@ proc find*(s: string, pattern: TRegEx, matches: var openarray[string], for i in 1..int(res)-1: var a = rawMatches[i * 2] var b = rawMatches[i * 2 + 1] - if a >= 0'i32: matches[i-1] = copy(s, int(a), int(b)-1) + if a >= 0'i32: matches[i-1] = substr(s, int(a), int(b)-1) else: matches[i-1] = "" return rawMatches[0] @@ -277,10 +277,10 @@ proc replace*(s: string, sub: TRegEx, by = ""): string = while true: var match = findBounds(s, sub, prev) if match.first < 0: break - add(result, copy(s, prev, match.first-1)) + add(result, substr(s, prev, match.first-1)) add(result, by) prev = match.last + 1 - add(result, copy(s, prev)) + add(result, substr(s, prev)) proc replacef*(s: string, sub: TRegEx, by: string): string = ## Replaces `sub` in `s` by the string `by`. Captures can be accessed in `by` @@ -300,10 +300,10 @@ proc replacef*(s: string, sub: TRegEx, by: string): string = while true: var match = findBounds(s, sub, caps, prev) if match.first < 0: break - add(result, copy(s, prev, match.first-1)) + add(result, substr(s, prev, match.first-1)) addf(result, by, caps) prev = match.last + 1 - add(result, copy(s, prev)) + add(result, substr(s, prev)) when false: result = "" var i = 0 @@ -316,8 +316,8 @@ proc replacef*(s: string, sub: TRegEx, by: string): string = else: addf(result, by, caps) inc(i, x) - # copy the rest: - add(result, copy(s, i)) + # substr the rest: + add(result, substr(s, i)) proc parallelReplace*(s: string, subs: openArray[ tuple[pattern: TRegEx, repl: string]]): string = @@ -337,7 +337,7 @@ proc parallelReplace*(s: string, subs: openArray[ add(result, s[i]) inc(i) # copy the rest: - add(result, copy(s, i)) + add(result, substr(s, i)) proc transformFile*(infile, outfile: string, subs: openArray[tuple[pattern: TRegEx, repl: string]]) = @@ -385,7 +385,7 @@ iterator split*(s: string, sep: TRegEx): string = x = matchLen(s, sep, last) if x > 0: break if first < last: - yield copy(s, first, last-1) + yield substr(s, first, last-1) proc split*(s: string, sep: TRegEx): seq[string] = ## Splits the string `s` into substrings. diff --git a/lib/pure/cgi.nim b/lib/pure/cgi.nim index af222caba..ae05d5734 100755 --- a/lib/pure/cgi.nim +++ b/lib/pure/cgi.nim @@ -36,7 +36,7 @@ proc URLencode*(s: string): string = ## ``{'A'..'Z', 'a'..'z', '0'..'9', '_'}`` are carried over to the result, ## a space is converted to ``'+'`` and every other character is encoded as ## ``'%xx'`` where ``xx`` denotes its hexadecimal value. - result = "" + result = newStringOfCap(s.len + s.len shr 2) # assume 12% non-alnum-chars for i in 0..s.len-1: case s[i] of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(result, s[i]) @@ -57,8 +57,9 @@ proc URLdecode*(s: string): string = ## is converted to a space, ``'%xx'`` (where ``xx`` denotes a hexadecimal ## value) is converted to the character with ordinal number ``xx``, and ## and every other character is carried over. - result = "" + result = newString(s.len) var i = 0 + var j = 0 while i < s.len: case s[i] of '%': @@ -66,10 +67,12 @@ proc URLdecode*(s: string): string = handleHexChar(s[i+1], x) handleHexChar(s[i+2], x) inc(i, 2) - add(result, chr(x)) - of '+': add(result, ' ') - else: add(result, s[i]) + result[j] = chr(x) + of '+': result[j] = ' ' + else: result[j] = s[i] inc(i) + inc(j) + setLen(result, j) proc addXmlChar(dest: var string, c: Char) {.inline.} = case c @@ -86,7 +89,7 @@ proc XMLencode*(s: string): string = ## * ``>`` is replaced by ``>`` ## * ``&`` is replaced by ``&`` ## * every other character is carried over. - result = "" + result = newStringOfCap(s.len + s.len shr 2) for i in 0..len(s)-1: addXmlChar(result, s[i]) type @@ -367,4 +370,8 @@ proc existsCookie*(name: string): bool = if gcookies == nil: gcookies = parseCookies(getHttpCookie()) result = hasKey(gcookies, name) +when isMainModule: + const test1 = "abc\L+def xyz" + assert UrlEncode(test1) == "abc%0A%2Bdef+xyz" + assert UrlDecode(UrlEncode(test1)) == test1 diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index eed6c7512..8e5de008c 100755 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -1,7 +1,7 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -24,7 +24,7 @@ proc parseCookies*(s: string): PStringTable = inc(i) # skip '=' var valstart = i while s[i] != ';' and s[i] != '\0': inc(i) - result[copy(s, keystart, keyend)] = copy(s, valstart, i-1) + result[substr(s, keystart, keyend)] = substr(s, valstart, i-1) if s[i] == '\0': break inc(i) # skip ';' diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 39ceb5f68..73a8cb853 100755 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -109,7 +109,7 @@ proc parseChunks(d: var string, start: int, s: TSocket): string = if charAt(d, i, s) == '\L': inc(i) else: httpError("CR-LF after chunksize expected") - var x = copy(d, i, i+chunkSize-1) + var x = substr(d, i, i+chunkSize-1) var size = x.len result.add(x) inc(i, size) @@ -133,7 +133,7 @@ proc parseBody(d: var string, start: int, s: TSocket, if headers["Transfer-Encoding"] == "chunked": result = parseChunks(d, start, s) else: - result = copy(d, start) + result = substr(d, start) # -REGION- Content-Length # (http://tools.ietf.org/html/rfc2616#section-4.4) NR.3 var contentLengthHeader = headers["Content-Length"] @@ -236,7 +236,7 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", ## | Extra headers can be specified and must be seperated by ``\c\L`` var r = parseUrl(url) - var headers = copy($httpMethod, len("http")) + var headers = substr($httpMethod, len("http")) headers.add(" /" & r.path & r.query) headers.add(" HTTP/1.1\c\L") diff --git a/lib/pure/httpserver.nim b/lib/pure/httpserver.nim index f8368a631..eb5dd7d73 100755 --- a/lib/pure/httpserver.nim +++ b/lib/pure/httpserver.nim @@ -121,7 +121,7 @@ proc executeCgi(client: TSocket, path, query: string, meth: TRequestMethod) = if L.startsWith("content-length:"): var i = len("content-length:") while L[i] in Whitespace: inc(i) - contentLength = parseInt(copy(L, i)) + contentLength = parseInt(substr(L, i)) if contentLength < 0: badRequest(client) @@ -165,7 +165,7 @@ proc acceptRequest(client: TSocket) = # extract path if q >= 0: # strip "?..." from path, this may be found in both POST and GET - path = "." & data[1].copy(0, q-1) + path = "." & data[1].substr(0, q-1) else: path = "." & data[1] # path starts with "/", by adding "." in front of it we serve files from cwd @@ -173,7 +173,7 @@ proc acceptRequest(client: TSocket) = if cmpIgnoreCase(data[0], "GET") == 0: if q >= 0: cgi = true - query = data[1].copy(q+1) + query = data[1].substr(q+1) elif cmpIgnoreCase(data[0], "POST") == 0: cgi = true meth = reqPost @@ -250,11 +250,11 @@ proc next*(s: var TServer) = if data[last] == '?' and query == 0: query = last inc(last) if query > 0: - s.query = data.copy(query+1, last-1) - s.path = data.copy(i, query-1) + s.query = data.substr(query+1, last-1) + s.path = data.substr(i, query-1) else: s.query = "" - s.path = data.copy(i, last-1) + s.path = data.substr(i, last-1) proc close*(s: TServer) = ## closes the server (and the socket the server uses). diff --git a/lib/pure/json.nim b/lib/pure/json.nim index adb7e5e8b..7b2707784 100755 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -649,7 +649,8 @@ proc nl(s: var string, ml: bool) = proc escapeJson*(s: string): string = ## Converts a string `s` to its JSON representation. - result = "\"" + result = newStringOfCap(s.len + s.len shr 3) + result.add("\"") for x in runes(s): var r = int(x) if r >= 32 and r <= 127: diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 7847fa332..2b2cb1ba7 100755 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -330,7 +330,7 @@ proc JoinPath*(head, tail: string): string {. result = tail elif head[len(head)-1] in {DirSep, AltSep}: if tail[0] in {DirSep, AltSep}: - result = head & copy(tail, 1) + result = head & substr(tail, 1) else: result = head & tail else: @@ -362,8 +362,8 @@ proc SplitPath*(path: string, head, tail: var string) {.noSideEffect, sepPos = i break if sepPos >= 0: - head = copy(path, 0, sepPos-1) - tail = copy(path, sepPos+1) + head = substr(path, 0, sepPos-1) + tail = substr(path, sepPos+1) else: head = "" tail = path # make a string copy here @@ -388,8 +388,8 @@ proc SplitPath*(path: string): tuple[head, tail: string] {. sepPos = i break if sepPos >= 0: - result.head = copy(path, 0, sepPos-1) - result.tail = copy(path, sepPos+1) + result.head = substr(path, 0, sepPos-1) + result.tail = substr(path, sepPos+1) else: result.head = "" result.tail = path @@ -412,7 +412,7 @@ proc parentDir*(path: string): string {. sepPos = i break if sepPos >= 0: - result = copy(path, 0, sepPos-1) + result = substr(path, 0, sepPos-1) else: result = path @@ -462,9 +462,9 @@ proc splitFile*(path: string): tuple[dir, name, ext: string] {. elif path[i] in {dirsep, altsep}: sepPos = i break - result.dir = copy(path, 0, sepPos-1) - result.name = copy(path, sepPos+1, dotPos-1) - result.ext = copy(path, dotPos) + result.dir = substr(path, 0, sepPos-1) + result.name = substr(path, sepPos+1, dotPos-1) + result.ext = substr(path, dotPos) proc extractDir*(path: string): string {.noSideEffect, deprecated.} = ## Extracts the directory of a given path. This is almost the @@ -507,8 +507,8 @@ proc SplitFilename*(filename: string, name, extension: var string) {. ## **Deprecated since version 0.8.2**: Use ``splitFile(filename)`` instead. var extPos = searchExtPos(filename) if extPos >= 0: - name = copy(filename, 0, extPos-1) - extension = copy(filename, extPos) + name = substr(filename, 0, extPos-1) + extension = substr(filename, extPos) else: name = filename # make a string copy here extension = "" @@ -537,7 +537,7 @@ proc ChangeFileExt*(filename, ext: string): string {. ## of none such beast.) var extPos = searchExtPos(filename) if extPos < 0: result = filename & normExt(ext) - else: result = copy(filename, 0, extPos-1) & normExt(ext) + else: result = substr(filename, 0, extPos-1) & normExt(ext) proc addFileExt*(filename, ext: string): string {. noSideEffect, rtl, extern: "nos$1".} = @@ -748,7 +748,7 @@ proc getEnv*(key: string): string = ## `existsEnv(key)`. var i = findEnvVar(key) if i >= 0: - return copy(environment[i], find(environment[i], '=')+1) + return substr(environment[i], find(environment[i], '=')+1) else: var env = cgetenv(key) if env == nil: return "" @@ -788,7 +788,7 @@ iterator iterOverEnvironment*(): tuple[key, value: string] {.deprecated.} = getEnvVarsC() for i in 0..high(environment): var p = find(environment[i], '=') - yield (copy(environment[i], 0, p-1), copy(environment[i], p+1)) + yield (substr(environment[i], 0, p-1), substr(environment[i], p+1)) iterator envPairs*(): tuple[key, value: string] = ## Iterate over all `environments variables`:idx:. In the first component @@ -797,7 +797,7 @@ iterator envPairs*(): tuple[key, value: string] = getEnvVarsC() for i in 0..high(environment): var p = find(environment[i], '=') - yield (copy(environment[i], 0, p-1), copy(environment[i], p+1)) + yield (substr(environment[i], 0, p-1), substr(environment[i], p+1)) iterator walkFiles*(pattern: string): string = ## Iterate over all the files that match the `pattern`. On POSIX this uses @@ -944,14 +944,14 @@ proc createDir*(dir: string) {.rtl, extern: "nos$1".} = ## fail if the path already exists because for most usages this does not ## indicate an error. for i in 1.. dir.len-1: - if dir[i] in {dirsep, altsep}: rawCreateDir(copy(dir, 0, i-1)) + if dir[i] in {dirsep, altsep}: rawCreateDir(substr(dir, 0, i-1)) rawCreateDir(dir) proc copyDir*(source, dest: string) {.rtl, extern: "nos$1".} = ## Copies a directory from `source` to `dest`. If this fails, `EOS` is raised. createDir(dest) for kind, path in walkDir(source): - var noSource = path.copy(source.len()+1) + var noSource = path.substr(source.len()+1) case kind of pcFile: copyFile(path, dest / noSource) diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim index 1b09934f2..c4625c161 100755 --- a/lib/pure/parseopt.nim +++ b/lib/pure/parseopt.nim @@ -126,7 +126,7 @@ proc next*(p: var TOptParser) {. proc cmdLineRest*(p: TOptParser): string {. rtl, extern: "npo$1".} = ## retrieves the rest of the command line that has not been parsed yet. - result = strip(copy(p.cmd, p.pos, len(p.cmd) - 1)) + result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1)) proc getRestOfCommandLine*(p: TOptParser): string {.deprecated.} = ## **Deprecated since version 0.8.2**: Use `cmdLineRest` instead. diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index 90bb5d79f..a7776bd5f 100755 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -73,7 +73,7 @@ proc parseIdent*(s: string, ident: var string, start = 0): int = if s[i] in IdentStartChars: inc(i) while s[i] in IdentChars: inc(i) - ident = copy(s, start, i-1) + ident = substr(s, start, i-1) result = i-start proc parseToken*(s: string, token: var string, validChars: set[char], @@ -86,7 +86,7 @@ proc parseToken*(s: string, token: var string, validChars: set[char], var i = start while s[i] in validChars: inc(i) result = i-start - token = copy(s, start, i-1) + token = substr(s, start, i-1) proc skipWhitespace*(s: string, start = 0): int {.inline.} = ## skips the whitespace starting at ``s[start]``. Returns the number of @@ -120,7 +120,7 @@ proc parseUntil*(s: string, token: var string, until: set[char], var i = start while s[i] notin until: inc(i) result = i-start - token = copy(s, start, i-1) + token = substr(s, start, i-1) proc parseWhile*(s: string, token: var string, validChars: set[char], start = 0): int {.inline.} = @@ -130,7 +130,7 @@ proc parseWhile*(s: string, token: var string, validChars: set[char], var i = start while s[i] in validChars: inc(i) result = i-start - token = copy(s, start, i-1) + token = substr(s, start, i-1) {.push overflowChecks: on.} # this must be compiled with overflow checking turned on: diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim index 9b2606b33..988e510e3 100755 --- a/lib/pure/pegs.nim +++ b/lib/pure/pegs.nim @@ -736,7 +736,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {. var (a, b) = c.matches[p.index] var n: TPeg n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef)) - n.term = s.copy(a, b) + n.term = s.substr(a, b) result = rawMatch(s, n, start, c) of pkStartAnchor: if c.origStart == start: result = 0 @@ -754,7 +754,7 @@ proc match*(s: string, pattern: TPeg, matches: var openarray[string], result = rawMatch(s, pattern, start, c) == len(s) - start if result: for i in 0..c.ml-1: - matches[i] = copy(s, c.matches[i][0], c.matches[i][1]) + matches[i] = substr(s, c.matches[i][0], c.matches[i][1]) proc match*(s: string, pattern: TPeg, start = 0): bool {.nosideEffect, rtl, extern: "npegs$1".} = @@ -774,7 +774,7 @@ proc matchLen*(s: string, pattern: TPeg, matches: var openarray[string], result = rawMatch(s, pattern, start, c) if result >= 0: for i in 0..c.ml-1: - matches[i] = copy(s, c.matches[i][0], c.matches[i][1]) + matches[i] = substr(s, c.matches[i][0], c.matches[i][1]) proc matchLen*(s: string, pattern: TPeg, start = 0): int {.nosideEffect, rtl, extern: "npegs$1".} = @@ -903,7 +903,7 @@ proc replacef*(s: string, sub: TPeg, by: string): string {. else: addf(result, by, caps) inc(i, x) - add(result, copy(s, i)) + add(result, substr(s, i)) proc replace*(s: string, sub: TPeg, by = ""): string {. nosideEffect, rtl, extern: "npegs$1".} = @@ -920,7 +920,7 @@ proc replace*(s: string, sub: TPeg, by = ""): string {. else: addf(result, by, caps) inc(i, x) - add(result, copy(s, i)) + add(result, substr(s, i)) proc parallelReplace*(s: string, subs: openArray[ tuple[pattern: TPeg, repl: string]]): string {. @@ -941,7 +941,7 @@ proc parallelReplace*(s: string, subs: openArray[ add(result, s[i]) inc(i) # copy the rest: - add(result, copy(s, i)) + add(result, substr(s, i)) proc transformFile*(infile, outfile: string, subs: openArray[tuple[pattern: TPeg, repl: string]]) {. @@ -990,7 +990,7 @@ iterator split*(s: string, sep: TPeg): string = x = matchLen(s, sep, last) if x > 0: break if first < last: - yield copy(s, first, last-1) + yield substr(s, first, last-1) proc split*(s: string, sep: TPeg): seq[string] {. nosideEffect, rtl, extern: "npegs$1".} = @@ -1688,7 +1688,7 @@ when isMainModule: assert rawMatch(s, expr.rule, 0, c) == len(s) var a = "" for i in 0..c.ml-1: - a.add(copy(s, c.matches[i][0], c.matches[i][1])) + a.add(substr(s, c.matches[i][0], c.matches[i][1])) assert a == "abcdef" #echo expr.rule diff --git a/lib/pure/regexprs.nim b/lib/pure/regexprs.nim index fb9601c18..3524aac0a 100755 --- a/lib/pure/regexprs.nim +++ b/lib/pure/regexprs.nim @@ -84,7 +84,7 @@ proc matchOrFind(s: string, pattern: PPcre, matches: var openarray[string], var a = rawMatches[i * 2] b = rawMatches[i * 2 + 1] - if a >= 0'i32: matches[i] = copy(s, a, int(b)-1) + if a >= 0'i32: matches[i] = substr(s, a, int(b)-1) else: matches[i] = "" return res diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim index 52406d4d1..69737576f 100755 --- a/lib/pure/ropes.nim +++ b/lib/pure/ropes.nim @@ -287,7 +287,7 @@ when false: if frmt[i] != '$': inc(i) else: break if i - 1 >= start: - add(result, copy(frmt, start, i-1)) + add(result, substr(frmt, start, i-1)) proc `%`*(frmt: string, args: openarray[PRope]): PRope {. rtl, extern: "nroFormat".} = @@ -330,7 +330,7 @@ proc `%`*(frmt: string, args: openarray[PRope]): PRope {. if frmt[i] != '$': inc(i) else: break if i - 1 >= start: - add(result, copy(frmt, start, i - 1)) + add(result, substr(frmt, start, i - 1)) proc addf*(c: var PRope, frmt: string, args: openarray[PRope]) {. rtl, extern: "nro$1".} = diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim index 78f489615..2028daa50 100755 --- a/lib/pure/strtabs.nim +++ b/lib/pure/strtabs.nim @@ -181,12 +181,12 @@ proc `%`*(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string {. of '{': var j = i + 1 while j < f.len and f[j] != '}': inc(j) - add(result, getValue(t, flags, copy(f, i+2, j-1))) + add(result, getValue(t, flags, substr(f, i+2, j-1))) i = j + 1 of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_': var j = i + 1 while j < f.len and f[j] in PatternChars: inc(j) - add(result, getValue(t, flags, copy(f, i+1, j-1))) + add(result, getValue(t, flags, substr(f, i+1, j-1))) i = j else: add(result, f[i]) diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 382eece7b..7ed224b67 100755 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -83,18 +83,22 @@ proc capitalize*(s: string): string {.noSideEffect, procvar, rtl, extern: "nsuCapitalize".} = ## Converts the first character of `s` into upper case. ## This works only for the letters a-z. - result = toUpper(s[0]) & copy(s, 1) + result = toUpper(s[0]) & substr(s, 1) proc normalize*(s: string): string {.noSideEffect, procvar, rtl, extern: "nsuNormalize".} = ## Normalizes the string `s`. That means to convert it to lower case and ## remove any '_'. This is needed for Nimrod identifiers for example. - result = "" + result = newString(s.len) + var j = 0 for i in 0..len(s) - 1: if s[i] in {'A'..'Z'}: - add result, Chr(Ord(s[i]) + (Ord('a') - Ord('A'))) + result[j] = Chr(Ord(s[i]) + (Ord('a') - Ord('A'))) + inc j elif s[i] != '_': - add result, s[i] + result[j] = s[i] + inc j + if j != s.len: setLen(result, j) proc cmpIgnoreCase*(a, b: string): int {.noSideEffect, rtl, extern: "nsuCmpIgnoreCase", procvar.} = @@ -171,14 +175,14 @@ proc addf*(s: var string, formatstr: string, a: openarray[string]) {. of '{': var j = i+1 while formatstr[j] notin {'\0', '}'}: inc(j) - var x = findNormalized(copy(formatstr, i+2, j-1), a) + var x = findNormalized(substr(formatstr, i+2, j-1), a) if x >= 0 and x < high(a): add s, a[x+1] else: raise newException(EInvalidValue, "invalid format string") i = j+1 of 'a'..'z', 'A'..'Z', '\128'..'\255', '_': var j = i+1 while formatstr[j] in PatternChars: inc(j) - var x = findNormalized(copy(formatstr, i+1, j-1), a) + var x = findNormalized(substr(formatstr, i+1, j-1), a) if x >= 0 and x < high(a): add s, a[x+1] else: raise newException(EInvalidValue, "invalid format string") i = j @@ -226,13 +230,14 @@ proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect, ## ## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is ## raised if an ill-formed format string has been passed to the `%` operator. - result = "" + result = newStringOfCap(formatstr.len + a.len shl 4) addf(result, formatstr, a) proc `%` *(formatstr, a: string): string {.noSideEffect, rtl, extern: "nsuFormatSingleElem".} = ## This is the same as ``formatstr % [a]``. - return formatstr % [a] + result = newStringOfCap(formatstr.len + a.len) + addf(result, formatstr, [a]) proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect, rtl, extern: "nsuStrip".} = @@ -248,7 +253,7 @@ proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect, while s[first] in chars: inc(first) if trailing: while last >= 0 and s[last] in chars: dec(last) - result = copy(s, first, last) + result = substr(s, first, last) proc toOctal*(c: char): string {.noSideEffect, rtl, extern: "nsuToOctal".} = ## Converts a character `c` to its octal representation. The resulting @@ -288,7 +293,7 @@ iterator split*(s: string, seps: set[char] = Whitespace): string = var first = last while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX! if first <= last-1: - yield copy(s, first, last-1) + yield substr(s, first, last-1) iterator split*(s: string, sep: char): string = ## Splits the string `s` into substrings. @@ -321,7 +326,7 @@ iterator split*(s: string, sep: char): string = while last <= len(s): var first = last while last < len(s) and s[last] != sep: inc(last) - yield copy(s, first, last-1) + yield substr(s, first, last-1) inc(last) iterator splitLines*(s: string): string = @@ -349,7 +354,7 @@ iterator splitLines*(s: string): string = var last = 0 while true: while s[last] notin {'\0', '\c', '\l'}: inc(last) - yield copy(s, first, last-1) + yield substr(s, first, last-1) # skip newlines: if s[last] == '\l': inc(last) elif s[last] == '\c': @@ -499,7 +504,7 @@ iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[ var isSep = s[j] in seps while j < s.len and (s[j] in seps) == isSep: inc(j) if j > i: - yield (copy(s, i, j-1), isSep) + yield (substr(s, i, j-1), isSep) else: break i = j @@ -510,19 +515,19 @@ proc wordWrap*(s: string, maxLineWidth = 80, newLine = "\n"): string {. noSideEffect, rtl, extern: "nsuWordWrap".} = ## word wraps `s`. - result = "" + result = newStringOfCap(s.len + s.len shr 6) var SpaceLeft = maxLineWidth for word, isSep in tokenize(s, seps): if len(word) > SpaceLeft: if splitLongWords and len(word) > maxLineWidth: - result.add(copy(word, 0, spaceLeft-1)) + result.add(substr(word, 0, spaceLeft-1)) var w = spaceLeft+1 var wordLeft = len(word) - spaceLeft while wordLeft > 0: result.add(newLine) var L = min(maxLineWidth, wordLeft) SpaceLeft = maxLineWidth - L - result.add(copy(word, w, w+L-1)) + result.add(substr(word, w, w+L-1)) inc(w, L) dec(wordLeft, L) else: @@ -700,11 +705,11 @@ proc replace*(s, sub: string, by = ""): string {.noSideEffect, while true: var j = findAux(s, sub, i, a) if j < 0: break - add result, copy(s, i, j - 1) + add result, substr(s, i, j - 1) add result, by i = j + len(sub) # copy the rest: - add result, copy(s, i) + add result, substr(s, i) proc replace*(s: string, sub, by: char): string {.noSideEffect, rtl, extern: "nsuReplaceChar".} = @@ -804,7 +809,8 @@ proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, ## The procedure has been designed so that its output is usable for many ## different common syntaxes. The resulting string is prefixed with ## `prefix` and suffixed with `suffix`. Both may be empty strings. - result = prefix + result = newStringOfCap(s.len + s.len shr 2) + result.add(prefix) for c in items(s): case c of '\0'..'\31', '\128'..'\255': @@ -837,7 +843,7 @@ proc validEmailAddress*(s: string): bool {.noSideEffect, while s[i] in {'0'..'9', 'a'..'z', '-', '.'}: inc(i) if s[i] != '\0': return false - var x = copy(s, j+1) + var x = substr(s, j+1) if len(x) == 2 and x[0] in Letters and x[1] in Letters: return true case toLower(x) of "com", "org", "net", "gov", "mil", "biz", "info", "mobi", "name", diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim index bf031fb88..923fc9e18 100755 --- a/lib/pure/xmldom.nim +++ b/lib/pure/xmldom.nim @@ -1021,9 +1021,9 @@ proc splitData*(TextNode: PText, offset: int): PText = if offset > TextNode.data.len(): raise newException(EIndexSizeErr, "Index out of bounds") - var left: string = TextNode.data.copy(0, offset) + var left: string = TextNode.data.substr(0, offset) TextNode.data = left - var right: string = TextNode.data.copy(offset, TextNode.data.len()) + var right: string = TextNode.data.substr(offset, TextNode.data.len()) if TextNode.FParentNode != nil: for i in low(TextNode.FParentNode.childNodes)..high(TextNode.FParentNode.childNodes): diff --git a/lib/system.nim b/lib/system.nim index bacb4325a..21da9d6ff 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -44,6 +44,10 @@ type typeDesc* {.magic: TypeDesc.} ## meta type to denote ## a type description (for templates) +const + hasThreadSupport = false # deactivate for now: thread stack walking + # is missing! + proc defined*[T](x: T): bool {.magic: "Defined", noSideEffect.} ## Special compile-time procedure that checks whether `x` is ## defined. `x` has to be an identifier or a qualified identifier. @@ -685,7 +689,13 @@ proc newString*(len: int): string {. ## content. One needs to fill the string character after character ## with the index operator ``s[i]``. This procedure exists only for ## optimization purposes; the same effect can be achieved with the - ## ``&`` operator. + ## ``&`` operator or with ``add``. + +proc newStringOfCap*(cap: int): string {. + magic: "NewStringOfCap", importc: "rawNewString", noSideEffect.} + ## returns a new string of length ``0`` but with capacity `cap`.This + ## procedure exists only for optimization purposes; the same effect can + ## be achieved with the ``&`` operator or with ``add``. proc `&` * (x: string, y: char): string {. magic: "ConStrStr", noSideEffect, merge.} @@ -899,8 +909,19 @@ proc addQuitProc*(QuitProc: proc {.noconv.}) {.importc: "atexit", nodecl.} # not be called explicitly! The user may decide to do this manually though. proc copy*(s: string, first = 0): string {. - magic: "CopyStr", importc: "copyStr", noSideEffect.} + magic: "CopyStr", importc: "copyStr", noSideEffect, deprecated.} proc copy*(s: string, first, last: int): string {. + magic: "CopyStrLast", importc: "copyStrLast", noSideEffect, + deprecated.} + ## copies a slice of `s` into a new string and returns this new + ## string. The bounds `first` and `last` denote the indices of + ## the first and last characters that shall be copied. If ``last`` + ## is omitted, it is treated as ``high(s)``. + ## **Deprecated since version 0.8.12**: Use ``substr`` instead. + +proc substr*(s: string, first = 0): string {. + magic: "CopyStr", importc: "copyStr", noSideEffect.} +proc substr*(s: string, first, last: int): string {. magic: "CopyStrLast", importc: "copyStrLast", noSideEffect.} ## copies a slice of `s` into a new string and returns this new ## string. The bounds `first` and `last` denote the indices of @@ -1219,21 +1240,21 @@ proc each*[T](data: var openArray[T], op: proc (x: var T)) = ## `op` to every item in `data`. for i in 0..data.len-1: op(data[i]) -iterator fields*(x: tuple[]): expr {.magic: "Fields", noSideEffect.} +iterator fields*[T: tuple](x: T): expr {.magic: "Fields", noSideEffect.} ## iterates over every field of `x`. Warning: This is really transforms ## the 'for' and unrolls the loop. The current implementation also has a bug ## that affects symbol binding in the loop body. -iterator fields*(x, y: tuple[]): tuple[a, b: expr] {. +iterator fields*[S: tuple, T: tuple](x: S, y: T): tuple[a, b: expr] {. magic: "Fields", noSideEffect.} ## iterates over every field of `x` and `y`. ## Warning: This is really transforms the 'for' and unrolls the loop. ## The current implementation also has a bug that affects symbol binding ## in the loop body. -iterator fieldPairs*(x: tuple[]): expr {.magic: "FieldPairs", noSideEffect.} +iterator fieldPairs*[T: tuple](x: T): expr {.magic: "FieldPairs", noSideEffect.} ## iterates over every field of `x`. Warning: This is really transforms ## the 'for' and unrolls the loop. The current implementation also has a bug ## that affects symbol binding in the loop body. -iterator fieldPairs*(x, y: tuple[]): tuple[a, b: expr] {. +iterator fieldPairs*[S: tuple, T: tuple](x: S, y: T): tuple[a, b: expr] {. magic: "FieldPairs", noSideEffect.} ## iterates over every field of `x` and `y`. ## Warning: This is really transforms the 'for' and unrolls the loop. @@ -1773,7 +1794,7 @@ template `-|`(b, s: expr): expr = proc `[]`*(s: string, x: TSlice[int]): string {.inline.} = ## slice operation for strings. Negative indexes are supported. - result = s.copy(x.a-|s, x.b-|s) + result = s.substr(x.a-|s, x.b-|s) proc `[]=`*(s: var string, x: TSlice[int], b: string) = ## slice assignment for strings. Negative indexes are supported. diff --git a/lib/system/cgprocs.nim b/lib/system/cgprocs.nim index f77768a7a..8509fe3a3 100755 --- a/lib/system/cgprocs.nim +++ b/lib/system/cgprocs.nim @@ -23,39 +23,50 @@ proc nimLoadLibraryError(path: string) {.compilerproc, noinline.} proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline.} -# Support for thread local storage: -when defined(windows): - type - TThreadVarSlot {.compilerproc.} = distinct int32 - - proc TlsAlloc(): TThreadVarSlot {. - importc: "TlsAlloc", stdcall, dynlib: "kernel32".} - proc TlsSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {. - importc: "TlsSetValue", stdcall, dynlib: "kernel32".} - proc TlsGetValue(dwTlsIndex: TThreadVarSlot): pointer {. - importc: "TlsGetValue", stdcall, dynlib: "kernel32".} - - proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} = - result = TlsAlloc() - proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.compilerproc.} = - TlsSetValue(s, value) - proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.compilerproc.} = - result = TlsGetValue(s) - -else: - type - Tpthread_key {.importc: "pthread_key_t", - header: "<sys/types.h>".} = distinct int - TThreadVarSlot {.compilerproc.} = Tpthread_key - - proc pthread_getspecific(a1: Tpthread_key): pointer {. - importc: "pthread_getspecific", header: "<pthread.h>".} - proc pthread_key_create(a1: ptr Tpthread_key, - destruct: proc (x: pointer) {.noconv.}): int32 {. - importc: "pthread_key_create", header: "<pthread.h>".} - proc pthread_key_delete(a1: Tpthread_key): int32 {. - importc: "pthread_key_delete", header: "<pthread.h>".} - - proc pthread_setspecific(a1: Tpthread_key, a2: pointer): int32 {. - importc: "pthread_setspecific", header: "<pthread.h>".} +when false: + # Support for thread local storage: + when defined(windows): + type + TThreadVarSlot {.compilerproc.} = distinct int32 + + proc TlsAlloc(): TThreadVarSlot {. + importc: "TlsAlloc", stdcall, dynlib: "kernel32".} + proc TlsSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {. + importc: "TlsSetValue", stdcall, dynlib: "kernel32".} + proc TlsGetValue(dwTlsIndex: TThreadVarSlot): pointer {. + importc: "TlsGetValue", stdcall, dynlib: "kernel32".} + + proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} = + result = TlsAlloc() + proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {. + compilerproc, inline.} = + TlsSetValue(s, value) + proc ThreadVarGetValue(s: TThreadVarSlot): pointer {. + compilerproc, inline.} = + result = TlsGetValue(s) + + else: + type + Tpthread_key {.importc: "pthread_key_t", + header: "<sys/types.h>".} = distinct int + TThreadVarSlot {.compilerproc.} = Tpthread_key + + proc pthread_getspecific(a1: Tpthread_key): pointer {. + importc: "pthread_getspecific", header: "<pthread.h>".} + proc pthread_key_create(a1: ptr Tpthread_key, + destruct: proc (x: pointer) {.noconv.}): int32 {. + importc: "pthread_key_create", header: "<pthread.h>".} + proc pthread_key_delete(a1: Tpthread_key): int32 {. + importc: "pthread_key_delete", header: "<pthread.h>".} + + proc pthread_setspecific(a1: Tpthread_key, a2: pointer): int32 {. + importc: "pthread_setspecific", header: "<pthread.h>".} + + proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} = + discard pthread_key_create(addr(result), nil) + proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {. + compilerproc, inline.} = + discard pthread_setspecific(s, value) + proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.compilerproc, inline.} = + result = pthread_getspecific(s) diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 073013113..ed2ec7ff0 100755 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -39,6 +39,8 @@ type exc: ref E_Base # XXX only needed for bootstrapping; unused context: C_JmpBuf +#when hasThreadSupport: nil + var excHandler {.threadvar, compilerproc.}: PSafePoint = nil # list of exception handlers diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 1edc33375..7c70ccf85 100755 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -626,10 +626,23 @@ else: # We use a jmp_buf buffer that is in the C stack. # Used to traverse the stack and registers assuming # that 'setjmp' will save registers in the C stack. + type PStackSlice = ptr array [0..7, pointer] var registers: C_JmpBuf if c_setjmp(registers) == 0'i32: # To fill the C stack with registers. var max = cast[TAddress](stackBottom) var sp = cast[TAddress](addr(registers)) + # loop unrolled: + while sp <% max - 8*sizeof(pointer): + gcMark(cast[PStackSlice](sp)[0]) + gcMark(cast[PStackSlice](sp)[1]) + gcMark(cast[PStackSlice](sp)[2]) + gcMark(cast[PStackSlice](sp)[3]) + gcMark(cast[PStackSlice](sp)[4]) + gcMark(cast[PStackSlice](sp)[5]) + gcMark(cast[PStackSlice](sp)[6]) + gcMark(cast[PStackSlice](sp)[7]) + sp = sp +% sizeof(pointer)*8 + # last few entries: while sp <=% max: gcMark(cast[ppointer](sp)[]) sp = sp +% sizeof(pointer) diff --git a/lib/system/repr.nim b/lib/system/repr.nim index 87588421f..9464ff3d8 100755 --- a/lib/system/repr.nim +++ b/lib/system/repr.nim @@ -111,7 +111,7 @@ type TReprClosure {.final.} = object # we cannot use a global variable here # as this wouldn't be thread-safe marked: TCellSet - recdepth: int # do not recurse endless + recdepth: int # do not recurse endlessly indent: int # indentation when not defined(useNimRtl): diff --git a/lib/system/systhread.nim b/lib/system/systhread.nim index 0ffc9605c..fa2d75704 100755 --- a/lib/system/systhread.nim +++ b/lib/system/systhread.nim @@ -8,8 +8,6 @@ # const - hasThreadSupport = false # deactivate for now: thread stack walking - # is missing! maxThreads = 256 when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport: diff --git a/tests/accept/compile/teval1.nim b/tests/accept/compile/teval1.nim new file mode 100644 index 000000000..8172ebe28 --- /dev/null +++ b/tests/accept/compile/teval1.nim @@ -0,0 +1,19 @@ +import macros + +proc testProc: string {.compileTime.} = + result = "" + result = result & "" + +when true: + macro test(n: stmt): stmt = + result = newNimNode(nnkStmtList) + echo "#", testProc(), "#" + test: + "hi" + +const + x = testProc() + +echo "##", x, "##" + + diff --git a/tests/accept/compile/tlibs.nim b/tests/accept/compile/tlibs.nim index 1f81a5ede..d4080eafd 100755 --- a/tests/accept/compile/tlibs.nim +++ b/tests/accept/compile/tlibs.nim @@ -15,7 +15,7 @@ import lua, lualib, lauxlib, mysql, sqlite3, python, tcl, db_postgres, db_mysql, db_sqlite, ropes, sockets, browsers, httpserver, httpclient, parseutils, unidecode, xmldom, xmldomparser, xmltree, xmlparser, - htmlparser, re, graphics, colors + htmlparser, re, graphics, colors, pegs when defined(linux): import diff --git a/todo.txt b/todo.txt index 1f1c31301..907fb790a 100755 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,6 @@ * thread support: threadvar on Windows seems broken; add --deadlock_prevention:on|off switch -- implicit ref/ptr->var conversion +* implicit ref/ptr->var conversion High priority (version 0.9.0) diff --git a/web/news.txt b/web/news.txt index f8bcef3db..dcfa6e363 100755 --- a/web/news.txt +++ b/web/news.txt @@ -31,6 +31,7 @@ Changes affecting backwards compatibility priority. - Deprecated ``os.getApplicationFilename``: Use ``os.getAppFilename`` instead. - Deprecated ``os.getApplicationDir``: Use ``os.getAppDir`` instead. +- Deprecated ``system.copy``: Use ``substr`` or string slicing instead. - Changed and documented how generalized string literals work: The syntax ``module.re"abc"`` is now supported. - Changed the behaviour of ``strutils.%``, ``ropes.%`` @@ -74,10 +75,11 @@ Additions - Added the ``linearScanEnd``, ``unroll``, ``shallow`` pragmas. - Added ``system.reset`` and a version of ``system.open`` that returns a ``TFile`` and raises an exception in case of an error. -- The compiler now might use a hashing for string case statements depending +- The compiler now might use hashing for string case statements depending on the number of string literals in the case statement. - Added a wrapper for ``redis``. - The compiler now supports array, sequence and string slicing. +- Added ``system.newStringOfCap``. 2010-10-20 Version 0.8.10 released |