Merge branch 'master' of github.com:Araq/Nimrod

This commit is contained in:
dom96 2011-05-14 20:35:17 +01:00
commit 4fd42d5150
43 changed files with 262 additions and 177 deletions

View file

@ -337,7 +337,9 @@ type
mFields, mFieldPairs, mFields, mFieldPairs,
mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendStrCh, mAppendStrStr, mAppendSeqElem,
mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, mAssert, 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, mArray, mOpenArray, mRange, mSet, mSeq,
mOrdinal, mInt, mInt8, mInt16, mInt32, mOrdinal, mInt, mInt8, mInt16, mInt32,
mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, mString, mCstring, mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, mString, mCstring,

View file

@ -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, of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
mInSet: mInSet:
genSetOp(p, e, d, op) 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 mReset: genReset(p, e)
of mEcho: genEcho(p, e) of mEcho: genEcho(p, e)
of mArrToSeq: genArrToSeq(p, e, d) of mArrToSeq: genArrToSeq(p, e, d)

View file

@ -210,7 +210,7 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: openarray[PRope]): PRope =
inc(i) inc(i)
var j = i var j = i
while frmt[j] in IdentChars: inc(j) while frmt[j] in IdentChars: inc(j)
var ident = copy(frmt, i, j-1) var ident = substr(frmt, i, j-1)
i = j i = j
app(result, cgsym(m, ident)) app(result, cgsym(m, ident))
elif frmt[i] == '#' and frmt[i+1] == '$': 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) if frmt[i] != '$' and frmt[i] != '#': inc(i)
else: break else: break
if i - 1 >= start: 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, proc appcg(m: BModule, c: var PRope, frmt: TFormatStr,
args: openarray[PRope]) = args: openarray[PRope]) =
@ -489,9 +489,9 @@ proc libCandidates(s: string, dest: var TStringSeq) =
var le = strutils.find(s, '(') var le = strutils.find(s, '(')
var ri = strutils.find(s, ')', le+1) var ri = strutils.find(s, ')', le+1)
if le >= 0 and ri > le: if le >= 0 and ri > le:
var prefix = copy(s, 0, le - 1) var prefix = substr(s, 0, le - 1)
var suffix = copy(s, ri + 1) var suffix = substr(s, ri + 1)
for middle in split(copy(s, le + 1, ri - 1), '|'): for middle in split(substr(s, le + 1, ri - 1), '|'):
libCandidates(prefix & middle & suffix, dest) libCandidates(prefix & middle & suffix, dest)
else: else:
add(dest, s) add(dest, s)

View file

@ -172,7 +172,7 @@ proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass,
else: break else: break
inc(i) inc(i)
if i >= len(switch): arg = "" 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) else: InvalidCmdLineOption(pass, switch, info)
proc ProcessOnOffSwitch(op: TOptions, arg: string, pass: TCmdlinePass, 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) var x = findStr(msgs.WarningsToStr, id)
if x >= 0: n = TNoteKind(x + ord(warnMin)) if x >= 0: n = TNoteKind(x + ord(warnMin))
else: InvalidCmdLineOption(pass, arg, info) else: InvalidCmdLineOption(pass, arg, info)
case whichKeyword(copy(arg, i)) case whichKeyword(substr(arg, i))
of wOn: incl(gNotes, n) of wOn: incl(gNotes, n)
of wOff: excl(gNotes, n) of wOff: excl(gNotes, n)
else: LocalError(info, errOnOrOffExpectedButXFound, arg) else: LocalError(info, errOnOrOffExpectedButXFound, arg)

View file

@ -156,7 +156,7 @@ proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openarray[string],
while i < L: while i < L:
if (frmt[i] != '$'): inc(i) if (frmt[i] != '$'): inc(i)
else: break 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) = proc addXmlChar(dest: var string, c: Char) =
case c case c
@ -581,10 +581,10 @@ proc renderCodeBlock(d: PDoc, n: PRstNode): PRope =
case g.kind case g.kind
of gtEof: break of gtEof: break
of gtNone, gtWhitespace: 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: else:
dispA(result, "<span class=\"$2\">$1</span>", "\\span$2{$1}", [ 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])]) toRope(tokenClassToStr[g.kind])])
deinitGeneralTokenizer(g) deinitGeneralTokenizer(g)
if result != nil: if result != nil:

View file

@ -990,7 +990,13 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
var a = result var a = result
result = newNodeIT(nkStrLit, n.info, n.typ) result = newNodeIT(nkStrLit, n.info, n.typ)
result.strVal = newString(int(getOrdValue(a))) 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], {}) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result

View file

@ -93,14 +93,14 @@ proc parseLine(p: var TTmplParser) =
of wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator, of wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator,
wConverter, wMacro, wTemplate, wMethod: wConverter, wMacro, wTemplate, wMethod:
LLStreamWrite(p.outp, repeatChar(p.indent)) LLStreamWrite(p.outp, repeatChar(p.indent))
LLStreamWrite(p.outp, copy(p.x, d)) LLStreamWrite(p.outp, substr(p.x, d))
inc(p.indent, 2) inc(p.indent, 2)
of wElif, wOf, wElse, wExcept, wFinally: of wElif, wOf, wElse, wExcept, wFinally:
LLStreamWrite(p.outp, repeatChar(p.indent - 2)) LLStreamWrite(p.outp, repeatChar(p.indent - 2))
LLStreamWrite(p.outp, copy(p.x, d)) LLStreamWrite(p.outp, substr(p.x, d))
else: else:
LLStreamWrite(p.outp, repeatChar(p.indent)) LLStreamWrite(p.outp, repeatChar(p.indent))
LLStreamWrite(p.outp, copy(p.x, d)) LLStreamWrite(p.outp, substr(p.x, d))
p.state = psDirective p.state = psDirective
else: else:
# data line # data line

View file

@ -216,7 +216,7 @@ proc LLStreamReadAll(s: PLLStream): string =
result = "" result = ""
of llsString: of llsString:
if s.rd == 0: result = s.s 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) s.rd = len(s.s)
of llsFile: of llsFile:
result = newString(bufSize) result = newString(bufSize)

View file

@ -33,8 +33,8 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
# we fix this here # we fix this here
var bracketLe = strutils.find(p.key, '[') var bracketLe = strutils.find(p.key, '[')
if bracketLe >= 0: if bracketLe >= 0:
var key = copy(p.key, 0, bracketLe - 1) var key = substr(p.key, 0, bracketLe - 1)
var val = copy(p.key, bracketLe + 1) & ':' & p.val var val = substr(p.key, bracketLe + 1) & ':' & p.val
ProcessSwitch(key, val, pass, cmdLineInfo) ProcessSwitch(key, val, pass, cmdLineInfo)
else: else:
ProcessSwitch(p.key, p.val, pass, cmdLineInfo) ProcessSwitch(p.key, p.val, pass, cmdLineInfo)

View file

@ -153,13 +153,13 @@ proc `%`(f: string, t: PStringTable, flags: TFormatFlags = {}): string =
of '{': of '{':
var j = i + 1 var j = i + 1
while (j <= len(f) + 0 - 1) and (f[j] != '}'): inc(j) 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)) add(result, getValue(t, flags, key))
i = j + 1 i = j + 1
of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_': of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_':
var j = i + 1 var j = i + 1
while (j <= len(f) + 0 - 1) and (f[j] in PatternChars): inc(j) 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)) add(result, getValue(t, flags, key))
i = j i = j
else: else:
@ -168,4 +168,4 @@ proc `%`(f: string, t: PStringTable, flags: TFormatFlags = {}): string =
else: else:
add(result, f[i]) add(result, f[i])
inc(i) inc(i)

View file

@ -138,19 +138,19 @@ proc shortenDir(dir: string): string =
# returns the interesting part of a dir # returns the interesting part of a dir
var prefix = getPrefixDir() & dirSep var prefix = getPrefixDir() & dirSep
if startsWith(dir, prefix): if startsWith(dir, prefix):
return copy(dir, len(prefix)) return substr(dir, len(prefix))
prefix = getCurrentDir() & dirSep prefix = getCurrentDir() & dirSep
if startsWith(dir, prefix): if startsWith(dir, prefix):
return copy(dir, len(prefix)) return substr(dir, len(prefix))
prefix = projectPath & dirSep #writeln(output, prefix); prefix = projectPath & dirSep #writeln(output, prefix);
#writeln(output, dir); #writeln(output, dir);
if startsWith(dir, prefix): if startsWith(dir, prefix):
return copy(dir, len(prefix)) return substr(dir, len(prefix))
result = dir result = dir
proc removeTrailingDirSep*(path: string): string = proc removeTrailingDirSep*(path: string): string =
if (len(path) > 0) and (path[len(path) - 1] == dirSep): 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: else:
result = path result = path

View file

@ -119,7 +119,7 @@ proc processMagic(c: PContext, n: PNode, s: PSym) =
# treat them as imported, instead of modifing a lot of working code # treat them as imported, instead of modifing a lot of working code
# BUGFIX: magic does not imply ``lfNoDecl`` anymore! # BUGFIX: magic does not imply ``lfNoDecl`` anymore!
for m in countup(low(TMagic), high(TMagic)): for m in countup(low(TMagic), high(TMagic)):
if copy($m, 1) == v: if substr($m, 1) == v:
s.magic = m s.magic = m
return return
Message(n.info, warnUnknownMagic, v) Message(n.info, warnUnknownMagic, v)
@ -333,12 +333,12 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
var a = 0 var a = 0
while true: while true:
var b = strutils.find(str, marker, a) 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 sub != "": addSon(result, newStrNode(nkStrLit, sub))
if b < 0: break if b < 0: break
var c = strutils.find(str, marker, b + 1) var c = strutils.find(str, marker, b + 1)
if c < 0: sub = copy(str, b + 1) if c < 0: sub = substr(str, b + 1)
else: sub = copy(str, b + 1, c - 1) else: sub = substr(str, b + 1, c - 1)
if sub != "": if sub != "":
var e = SymtabGet(con.tab, getIdent(sub)) var e = SymtabGet(con.tab, getIdent(sub))
if e != nil: if e != nil:

View file

@ -1106,7 +1106,7 @@ proc getNextTok(r: var TSrcGen, kind: var TTokType, literal: var string) =
if r.idx < len(r.tokens): if r.idx < len(r.tokens):
kind = r.tokens[r.idx].kind kind = r.tokens[r.idx].kind
var length = r.tokens[r.idx].length 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.pos, length)
inc(r.idx) inc(r.idx)
else: else:

View file

@ -328,7 +328,7 @@ proc ropef(frmt: TFormatStr, args: openarray[PRope]): PRope =
if (frmt[i] != '$'): inc(i) if (frmt[i] != '$'): inc(i)
else: break else: break
if i - 1 >= start: if i - 1 >= start:
app(result, copy(frmt, start, i - 1)) app(result, substr(frmt, start, i - 1))
assert(RopeInvariant(result)) assert(RopeInvariant(result))
proc appf(c: var PRope, frmt: TFormatStr, args: openarray[PRope]) = proc appf(c: var PRope, frmt: TFormatStr, args: openarray[PRope]) =

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -189,9 +189,9 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
of mBoolToStr: of mBoolToStr:
if getOrdValue(a) == 0: result = newStrNodeT("false", n) if getOrdValue(a) == 0: result = newStrNodeT("false", n)
else: result = newStrNodeT("true", 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: of mCopyStrLast:
result = newStrNodeT(copy(getStr(a), int(getOrdValue(b)), result = newStrNodeT(substr(getStr(a), int(getOrdValue(b)),
int(getOrdValue(c))), n) int(getOrdValue(c))), n)
of mFloatToStr: result = newStrNodeT($(getFloat(a)), n) of mFloatToStr: result = newStrNodeT($(getFloat(a)), n)
of mCStrToStr, mCharToStr: result = newStrNodeT(getStrOrChar(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: of mCompileOptionArg:
result = newIntNodeT(Ord( result = newIntNodeT(Ord(
testCompileOptionArg(getStr(a), getStr(b), n.info)), n) 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, mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
mNLen..mNError, mEqRef: mNLen..mNError, mEqRef:
nil nil

View file

@ -14,7 +14,7 @@ import
ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
magicsys magicsys
type type
TCandidateState* = enum TCandidateState* = enum
csEmpty, csMatch, csNoMatch csEmpty, csMatch, csNoMatch
TCandidate* {.final.} = object TCandidate* {.final.} = object
@ -33,7 +33,6 @@ type
TTypeRelation* = enum # order is important! TTypeRelation* = enum # order is important!
isNone, isConvertible, isIntConv, isSubtype, isNone, isConvertible, isIntConv, isSubtype,
isLifted, # match, but do not change argument type to formal's type!
isGeneric, isGeneric,
isEqual isEqual
@ -185,9 +184,6 @@ proc tupleRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
var x = f.n.sons[i].sym var x = f.n.sons[i].sym
var y = a.n.sons[i].sym var y = a.n.sons[i].sym
if x.name.id != y.name.id: return isNone 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 = proc constraintRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
result = isNone result = isNone
@ -226,7 +222,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
of tyFloat64: result = handleFloatRange(f, a) of tyFloat64: result = handleFloatRange(f, a)
of tyFloat128: result = handleFloatRange(f, a) of tyFloat128: result = handleFloatRange(f, a)
of tyVar: 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) else: result = typeRel(mapping, base(f), a)
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
# tyArrayConstr cannot happen really, but # tyArrayConstr cannot happen really, but
@ -493,9 +489,6 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
of isSubtype: of isSubtype:
inc(m.subtypeMatches) inc(m.subtypeMatches)
result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c) result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c)
of isLifted:
inc(m.genericMatches)
result = copyTree(arg)
of isGeneric: of isGeneric:
inc(m.genericMatches) inc(m.genericMatches)
result = copyTree(arg) result = copyTree(arg)

View file

@ -98,7 +98,7 @@ proc parsePipe(filename: string, inputStream: PLLStream): PNode =
inc(i, 2) inc(i, 2)
while line[i] in WhiteSpace: inc(i) while line[i] in WhiteSpace: inc(i)
var q: TParser var q: TParser
OpenParser(q, filename, LLStreamOpen(copy(line, i))) OpenParser(q, filename, LLStreamOpen(substr(line, i)))
result = parser.parseAll(q) result = parser.parseAll(q)
CloseParser(q) CloseParser(q)
LLStreamClose(s) LLStreamClose(s)

View file

@ -32,6 +32,7 @@ get get, ``[]`` consider overloading ``[]`` for get;
prefix: ``len`` instead of ``getLen`` prefix: ``len`` instead of ``getLen``
length len also used for *number of elements* length len also used for *number of elements*
size size, len size should refer to a byte size size size, len size should refer to a byte size
capacity cap
memory mem implies a low-level operation memory mem implies a low-level operation
items items default iterator over a collection items items default iterator over a collection
pairs pairs iterator over (key, value) pairs pairs pairs iterator over (key, value) pairs
@ -69,6 +70,7 @@ coordinate coord
rectangle rect rectangle rect
point point point point
symbol sym symbol sym
string str
identifier ident identifier ident
indentation indent indentation indent
------------------- ------------ -------------------------------------- ------------------- ------------ --------------------------------------

View file

@ -88,7 +88,7 @@ proc matchOrFind(s: string, pattern: TRegEx, matches: var openarray[string],
for i in 1..int(res)-1: for i in 1..int(res)-1:
var a = rawMatches[i * 2] var a = rawMatches[i * 2]
var b = rawMatches[i * 2 + 1] 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] = "" else: matches[i-1] = ""
return rawMatches[1] - rawMatches[0] 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: for i in 1..int(res)-1:
var a = rawMatches[i * 2] var a = rawMatches[i * 2]
var b = rawMatches[i * 2 + 1] 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] = "" else: matches[i-1] = ""
return (rawMatches[0].int, rawMatches[1].int - 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: for i in 1..int(res)-1:
var a = rawMatches[i * 2] var a = rawMatches[i * 2]
var b = rawMatches[i * 2 + 1] 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] = "" else: matches[i-1] = ""
return rawMatches[0] return rawMatches[0]
@ -277,10 +277,10 @@ proc replace*(s: string, sub: TRegEx, by = ""): string =
while true: while true:
var match = findBounds(s, sub, prev) var match = findBounds(s, sub, prev)
if match.first < 0: break if match.first < 0: break
add(result, copy(s, prev, match.first-1)) add(result, substr(s, prev, match.first-1))
add(result, by) add(result, by)
prev = match.last + 1 prev = match.last + 1
add(result, copy(s, prev)) add(result, substr(s, prev))
proc replacef*(s: string, sub: TRegEx, by: string): string = proc replacef*(s: string, sub: TRegEx, by: string): string =
## Replaces `sub` in `s` by the string `by`. Captures can be accessed in `by` ## 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: while true:
var match = findBounds(s, sub, caps, prev) var match = findBounds(s, sub, caps, prev)
if match.first < 0: break 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) addf(result, by, caps)
prev = match.last + 1 prev = match.last + 1
add(result, copy(s, prev)) add(result, substr(s, prev))
when false: when false:
result = "" result = ""
var i = 0 var i = 0
@ -316,8 +316,8 @@ proc replacef*(s: string, sub: TRegEx, by: string): string =
else: else:
addf(result, by, caps) addf(result, by, caps)
inc(i, x) inc(i, x)
# copy the rest: # substr the rest:
add(result, copy(s, i)) add(result, substr(s, i))
proc parallelReplace*(s: string, subs: openArray[ proc parallelReplace*(s: string, subs: openArray[
tuple[pattern: TRegEx, repl: string]]): string = tuple[pattern: TRegEx, repl: string]]): string =
@ -337,7 +337,7 @@ proc parallelReplace*(s: string, subs: openArray[
add(result, s[i]) add(result, s[i])
inc(i) inc(i)
# copy the rest: # copy the rest:
add(result, copy(s, i)) add(result, substr(s, i))
proc transformFile*(infile, outfile: string, proc transformFile*(infile, outfile: string,
subs: openArray[tuple[pattern: TRegEx, repl: string]]) = subs: openArray[tuple[pattern: TRegEx, repl: string]]) =
@ -385,7 +385,7 @@ iterator split*(s: string, sep: TRegEx): string =
x = matchLen(s, sep, last) x = matchLen(s, sep, last)
if x > 0: break if x > 0: break
if first < last: if first < last:
yield copy(s, first, last-1) yield substr(s, first, last-1)
proc split*(s: string, sep: TRegEx): seq[string] = proc split*(s: string, sep: TRegEx): seq[string] =
## Splits the string `s` into substrings. ## Splits the string `s` into substrings.

View file

@ -36,7 +36,7 @@ proc URLencode*(s: string): string =
## ``{'A'..'Z', 'a'..'z', '0'..'9', '_'}`` are carried over to the result, ## ``{'A'..'Z', 'a'..'z', '0'..'9', '_'}`` are carried over to the result,
## a space is converted to ``'+'`` and every other character is encoded as ## a space is converted to ``'+'`` and every other character is encoded as
## ``'%xx'`` where ``xx`` denotes its hexadecimal value. ## ``'%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: for i in 0..s.len-1:
case s[i] case s[i]
of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(result, 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 ## is converted to a space, ``'%xx'`` (where ``xx`` denotes a hexadecimal
## value) is converted to the character with ordinal number ``xx``, and ## value) is converted to the character with ordinal number ``xx``, and
## and every other character is carried over. ## and every other character is carried over.
result = "" result = newString(s.len)
var i = 0 var i = 0
var j = 0
while i < s.len: while i < s.len:
case s[i] case s[i]
of '%': of '%':
@ -66,10 +67,12 @@ proc URLdecode*(s: string): string =
handleHexChar(s[i+1], x) handleHexChar(s[i+1], x)
handleHexChar(s[i+2], x) handleHexChar(s[i+2], x)
inc(i, 2) inc(i, 2)
add(result, chr(x)) result[j] = chr(x)
of '+': add(result, ' ') of '+': result[j] = ' '
else: add(result, s[i]) else: result[j] = s[i]
inc(i) inc(i)
inc(j)
setLen(result, j)
proc addXmlChar(dest: var string, c: Char) {.inline.} = proc addXmlChar(dest: var string, c: Char) {.inline.} =
case c case c
@ -86,7 +89,7 @@ proc XMLencode*(s: string): string =
## * ``>`` is replaced by ``&gt;`` ## * ``>`` is replaced by ``&gt;``
## * ``&`` is replaced by ``&amp;`` ## * ``&`` is replaced by ``&amp;``
## * every other character is carried over. ## * 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]) for i in 0..len(s)-1: addXmlChar(result, s[i])
type type
@ -367,4 +370,8 @@ proc existsCookie*(name: string): bool =
if gcookies == nil: gcookies = parseCookies(getHttpCookie()) if gcookies == nil: gcookies = parseCookies(getHttpCookie())
result = hasKey(gcookies, name) result = hasKey(gcookies, name)
when isMainModule:
const test1 = "abc\L+def xyz"
assert UrlEncode(test1) == "abc%0A%2Bdef+xyz"
assert UrlDecode(UrlEncode(test1)) == test1

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -24,7 +24,7 @@ proc parseCookies*(s: string): PStringTable =
inc(i) # skip '=' inc(i) # skip '='
var valstart = i var valstart = i
while s[i] != ';' and s[i] != '\0': inc(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 if s[i] == '\0': break
inc(i) # skip ';' inc(i) # skip ';'

View file

@ -109,7 +109,7 @@ proc parseChunks(d: var string, start: int, s: TSocket): string =
if charAt(d, i, s) == '\L': inc(i) if charAt(d, i, s) == '\L': inc(i)
else: httpError("CR-LF after chunksize expected") 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 var size = x.len
result.add(x) result.add(x)
inc(i, size) inc(i, size)
@ -133,7 +133,7 @@ proc parseBody(d: var string, start: int, s: TSocket,
if headers["Transfer-Encoding"] == "chunked": if headers["Transfer-Encoding"] == "chunked":
result = parseChunks(d, start, s) result = parseChunks(d, start, s)
else: else:
result = copy(d, start) result = substr(d, start)
# -REGION- Content-Length # -REGION- Content-Length
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.3 # (http://tools.ietf.org/html/rfc2616#section-4.4) NR.3
var contentLengthHeader = headers["Content-Length"] 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`` ## | Extra headers can be specified and must be seperated by ``\c\L``
var r = parseUrl(url) var r = parseUrl(url)
var headers = copy($httpMethod, len("http")) var headers = substr($httpMethod, len("http"))
headers.add(" /" & r.path & r.query) headers.add(" /" & r.path & r.query)
headers.add(" HTTP/1.1\c\L") headers.add(" HTTP/1.1\c\L")

View file

@ -121,7 +121,7 @@ proc executeCgi(client: TSocket, path, query: string, meth: TRequestMethod) =
if L.startsWith("content-length:"): if L.startsWith("content-length:"):
var i = len("content-length:") var i = len("content-length:")
while L[i] in Whitespace: inc(i) while L[i] in Whitespace: inc(i)
contentLength = parseInt(copy(L, i)) contentLength = parseInt(substr(L, i))
if contentLength < 0: if contentLength < 0:
badRequest(client) badRequest(client)
@ -165,7 +165,7 @@ proc acceptRequest(client: TSocket) =
# extract path # extract path
if q >= 0: if q >= 0:
# strip "?..." from path, this may be found in both POST and GET # 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: else:
path = "." & data[1] path = "." & data[1]
# path starts with "/", by adding "." in front of it we serve files from cwd # 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 cmpIgnoreCase(data[0], "GET") == 0:
if q >= 0: if q >= 0:
cgi = true cgi = true
query = data[1].copy(q+1) query = data[1].substr(q+1)
elif cmpIgnoreCase(data[0], "POST") == 0: elif cmpIgnoreCase(data[0], "POST") == 0:
cgi = true cgi = true
meth = reqPost meth = reqPost
@ -250,11 +250,11 @@ proc next*(s: var TServer) =
if data[last] == '?' and query == 0: query = last if data[last] == '?' and query == 0: query = last
inc(last) inc(last)
if query > 0: if query > 0:
s.query = data.copy(query+1, last-1) s.query = data.substr(query+1, last-1)
s.path = data.copy(i, query-1) s.path = data.substr(i, query-1)
else: else:
s.query = "" s.query = ""
s.path = data.copy(i, last-1) s.path = data.substr(i, last-1)
proc close*(s: TServer) = proc close*(s: TServer) =
## closes the server (and the socket the server uses). ## closes the server (and the socket the server uses).

View file

@ -649,7 +649,8 @@ proc nl(s: var string, ml: bool) =
proc escapeJson*(s: string): string = proc escapeJson*(s: string): string =
## Converts a string `s` to its JSON representation. ## Converts a string `s` to its JSON representation.
result = "\"" result = newStringOfCap(s.len + s.len shr 3)
result.add("\"")
for x in runes(s): for x in runes(s):
var r = int(x) var r = int(x)
if r >= 32 and r <= 127: if r >= 32 and r <= 127:

View file

@ -330,7 +330,7 @@ proc JoinPath*(head, tail: string): string {.
result = tail result = tail
elif head[len(head)-1] in {DirSep, AltSep}: elif head[len(head)-1] in {DirSep, AltSep}:
if tail[0] in {DirSep, AltSep}: if tail[0] in {DirSep, AltSep}:
result = head & copy(tail, 1) result = head & substr(tail, 1)
else: else:
result = head & tail result = head & tail
else: else:
@ -362,8 +362,8 @@ proc SplitPath*(path: string, head, tail: var string) {.noSideEffect,
sepPos = i sepPos = i
break break
if sepPos >= 0: if sepPos >= 0:
head = copy(path, 0, sepPos-1) head = substr(path, 0, sepPos-1)
tail = copy(path, sepPos+1) tail = substr(path, sepPos+1)
else: else:
head = "" head = ""
tail = path # make a string copy here tail = path # make a string copy here
@ -388,8 +388,8 @@ proc SplitPath*(path: string): tuple[head, tail: string] {.
sepPos = i sepPos = i
break break
if sepPos >= 0: if sepPos >= 0:
result.head = copy(path, 0, sepPos-1) result.head = substr(path, 0, sepPos-1)
result.tail = copy(path, sepPos+1) result.tail = substr(path, sepPos+1)
else: else:
result.head = "" result.head = ""
result.tail = path result.tail = path
@ -412,7 +412,7 @@ proc parentDir*(path: string): string {.
sepPos = i sepPos = i
break break
if sepPos >= 0: if sepPos >= 0:
result = copy(path, 0, sepPos-1) result = substr(path, 0, sepPos-1)
else: else:
result = path result = path
@ -462,9 +462,9 @@ proc splitFile*(path: string): tuple[dir, name, ext: string] {.
elif path[i] in {dirsep, altsep}: elif path[i] in {dirsep, altsep}:
sepPos = i sepPos = i
break break
result.dir = copy(path, 0, sepPos-1) result.dir = substr(path, 0, sepPos-1)
result.name = copy(path, sepPos+1, dotPos-1) result.name = substr(path, sepPos+1, dotPos-1)
result.ext = copy(path, dotPos) result.ext = substr(path, dotPos)
proc extractDir*(path: string): string {.noSideEffect, deprecated.} = proc extractDir*(path: string): string {.noSideEffect, deprecated.} =
## Extracts the directory of a given path. This is almost the ## 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. ## **Deprecated since version 0.8.2**: Use ``splitFile(filename)`` instead.
var extPos = searchExtPos(filename) var extPos = searchExtPos(filename)
if extPos >= 0: if extPos >= 0:
name = copy(filename, 0, extPos-1) name = substr(filename, 0, extPos-1)
extension = copy(filename, extPos) extension = substr(filename, extPos)
else: else:
name = filename # make a string copy here name = filename # make a string copy here
extension = "" extension = ""
@ -537,7 +537,7 @@ proc ChangeFileExt*(filename, ext: string): string {.
## of none such beast.) ## of none such beast.)
var extPos = searchExtPos(filename) var extPos = searchExtPos(filename)
if extPos < 0: result = filename & normExt(ext) 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 {. proc addFileExt*(filename, ext: string): string {.
noSideEffect, rtl, extern: "nos$1".} = noSideEffect, rtl, extern: "nos$1".} =
@ -748,7 +748,7 @@ proc getEnv*(key: string): string =
## `existsEnv(key)`. ## `existsEnv(key)`.
var i = findEnvVar(key) var i = findEnvVar(key)
if i >= 0: if i >= 0:
return copy(environment[i], find(environment[i], '=')+1) return substr(environment[i], find(environment[i], '=')+1)
else: else:
var env = cgetenv(key) var env = cgetenv(key)
if env == nil: return "" if env == nil: return ""
@ -788,7 +788,7 @@ iterator iterOverEnvironment*(): tuple[key, value: string] {.deprecated.} =
getEnvVarsC() getEnvVarsC()
for i in 0..high(environment): for i in 0..high(environment):
var p = find(environment[i], '=') 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] = iterator envPairs*(): tuple[key, value: string] =
## Iterate over all `environments variables`:idx:. In the first component ## Iterate over all `environments variables`:idx:. In the first component
@ -797,7 +797,7 @@ iterator envPairs*(): tuple[key, value: string] =
getEnvVarsC() getEnvVarsC()
for i in 0..high(environment): for i in 0..high(environment):
var p = find(environment[i], '=') 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 = iterator walkFiles*(pattern: string): string =
## Iterate over all the files that match the `pattern`. On POSIX this uses ## 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 ## fail if the path already exists because for most usages this does not
## indicate an error. ## indicate an error.
for i in 1.. dir.len-1: 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) rawCreateDir(dir)
proc copyDir*(source, dest: string) {.rtl, extern: "nos$1".} = proc copyDir*(source, dest: string) {.rtl, extern: "nos$1".} =
## Copies a directory from `source` to `dest`. If this fails, `EOS` is raised. ## Copies a directory from `source` to `dest`. If this fails, `EOS` is raised.
createDir(dest) createDir(dest)
for kind, path in walkDir(source): for kind, path in walkDir(source):
var noSource = path.copy(source.len()+1) var noSource = path.substr(source.len()+1)
case kind case kind
of pcFile: of pcFile:
copyFile(path, dest / noSource) copyFile(path, dest / noSource)

View file

@ -126,7 +126,7 @@ proc next*(p: var TOptParser) {.
proc cmdLineRest*(p: TOptParser): string {. proc cmdLineRest*(p: TOptParser): string {.
rtl, extern: "npo$1".} = rtl, extern: "npo$1".} =
## retrieves the rest of the command line that has not been parsed yet. ## 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.} = proc getRestOfCommandLine*(p: TOptParser): string {.deprecated.} =
## **Deprecated since version 0.8.2**: Use `cmdLineRest` instead. ## **Deprecated since version 0.8.2**: Use `cmdLineRest` instead.

View file

@ -73,7 +73,7 @@ proc parseIdent*(s: string, ident: var string, start = 0): int =
if s[i] in IdentStartChars: if s[i] in IdentStartChars:
inc(i) inc(i)
while s[i] in IdentChars: inc(i) while s[i] in IdentChars: inc(i)
ident = copy(s, start, i-1) ident = substr(s, start, i-1)
result = i-start result = i-start
proc parseToken*(s: string, token: var string, validChars: set[char], 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 var i = start
while s[i] in validChars: inc(i) while s[i] in validChars: inc(i)
result = i-start result = i-start
token = copy(s, start, i-1) token = substr(s, start, i-1)
proc skipWhitespace*(s: string, start = 0): int {.inline.} = proc skipWhitespace*(s: string, start = 0): int {.inline.} =
## skips the whitespace starting at ``s[start]``. Returns the number of ## 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 var i = start
while s[i] notin until: inc(i) while s[i] notin until: inc(i)
result = i-start 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], proc parseWhile*(s: string, token: var string, validChars: set[char],
start = 0): int {.inline.} = start = 0): int {.inline.} =
@ -130,7 +130,7 @@ proc parseWhile*(s: string, token: var string, validChars: set[char],
var i = start var i = start
while s[i] in validChars: inc(i) while s[i] in validChars: inc(i)
result = i-start result = i-start
token = copy(s, start, i-1) token = substr(s, start, i-1)
{.push overflowChecks: on.} {.push overflowChecks: on.}
# this must be compiled with overflow checking turned on: # this must be compiled with overflow checking turned on:

View file

@ -736,7 +736,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
var (a, b) = c.matches[p.index] var (a, b) = c.matches[p.index]
var n: TPeg var n: TPeg
n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef)) 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) result = rawMatch(s, n, start, c)
of pkStartAnchor: of pkStartAnchor:
if c.origStart == start: result = 0 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 result = rawMatch(s, pattern, start, c) == len(s) - start
if result: if result:
for i in 0..c.ml-1: 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, proc match*(s: string, pattern: TPeg,
start = 0): bool {.nosideEffect, rtl, extern: "npegs$1".} = 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) result = rawMatch(s, pattern, start, c)
if result >= 0: if result >= 0:
for i in 0..c.ml-1: 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, proc matchLen*(s: string, pattern: TPeg,
start = 0): int {.nosideEffect, rtl, extern: "npegs$1".} = start = 0): int {.nosideEffect, rtl, extern: "npegs$1".} =
@ -903,7 +903,7 @@ proc replacef*(s: string, sub: TPeg, by: string): string {.
else: else:
addf(result, by, caps) addf(result, by, caps)
inc(i, x) inc(i, x)
add(result, copy(s, i)) add(result, substr(s, i))
proc replace*(s: string, sub: TPeg, by = ""): string {. proc replace*(s: string, sub: TPeg, by = ""): string {.
nosideEffect, rtl, extern: "npegs$1".} = nosideEffect, rtl, extern: "npegs$1".} =
@ -920,7 +920,7 @@ proc replace*(s: string, sub: TPeg, by = ""): string {.
else: else:
addf(result, by, caps) addf(result, by, caps)
inc(i, x) inc(i, x)
add(result, copy(s, i)) add(result, substr(s, i))
proc parallelReplace*(s: string, subs: openArray[ proc parallelReplace*(s: string, subs: openArray[
tuple[pattern: TPeg, repl: string]]): string {. tuple[pattern: TPeg, repl: string]]): string {.
@ -941,7 +941,7 @@ proc parallelReplace*(s: string, subs: openArray[
add(result, s[i]) add(result, s[i])
inc(i) inc(i)
# copy the rest: # copy the rest:
add(result, copy(s, i)) add(result, substr(s, i))
proc transformFile*(infile, outfile: string, proc transformFile*(infile, outfile: string,
subs: openArray[tuple[pattern: TPeg, repl: string]]) {. subs: openArray[tuple[pattern: TPeg, repl: string]]) {.
@ -990,7 +990,7 @@ iterator split*(s: string, sep: TPeg): string =
x = matchLen(s, sep, last) x = matchLen(s, sep, last)
if x > 0: break if x > 0: break
if first < last: if first < last:
yield copy(s, first, last-1) yield substr(s, first, last-1)
proc split*(s: string, sep: TPeg): seq[string] {. proc split*(s: string, sep: TPeg): seq[string] {.
nosideEffect, rtl, extern: "npegs$1".} = nosideEffect, rtl, extern: "npegs$1".} =
@ -1688,7 +1688,7 @@ when isMainModule:
assert rawMatch(s, expr.rule, 0, c) == len(s) assert rawMatch(s, expr.rule, 0, c) == len(s)
var a = "" var a = ""
for i in 0..c.ml-1: 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" assert a == "abcdef"
#echo expr.rule #echo expr.rule

View file

@ -84,7 +84,7 @@ proc matchOrFind(s: string, pattern: PPcre, matches: var openarray[string],
var var
a = rawMatches[i * 2] a = rawMatches[i * 2]
b = rawMatches[i * 2 + 1] 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] = "" else: matches[i] = ""
return res return res

View file

@ -287,7 +287,7 @@ when false:
if frmt[i] != '$': inc(i) if frmt[i] != '$': inc(i)
else: break else: break
if i - 1 >= start: 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 {. proc `%`*(frmt: string, args: openarray[PRope]): PRope {.
rtl, extern: "nroFormat".} = rtl, extern: "nroFormat".} =
@ -330,7 +330,7 @@ proc `%`*(frmt: string, args: openarray[PRope]): PRope {.
if frmt[i] != '$': inc(i) if frmt[i] != '$': inc(i)
else: break else: break
if i - 1 >= start: 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]) {. proc addf*(c: var PRope, frmt: string, args: openarray[PRope]) {.
rtl, extern: "nro$1".} = rtl, extern: "nro$1".} =

View file

@ -181,12 +181,12 @@ proc `%`*(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string {.
of '{': of '{':
var j = i + 1 var j = i + 1
while j < f.len and f[j] != '}': inc(j) 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 i = j + 1
of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_': of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_':
var j = i + 1 var j = i + 1
while j < f.len and f[j] in PatternChars: inc(j) 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 i = j
else: else:
add(result, f[i]) add(result, f[i])

View file

@ -83,18 +83,22 @@ proc capitalize*(s: string): string {.noSideEffect, procvar,
rtl, extern: "nsuCapitalize".} = rtl, extern: "nsuCapitalize".} =
## Converts the first character of `s` into upper case. ## Converts the first character of `s` into upper case.
## This works only for the letters a-z. ## 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, proc normalize*(s: string): string {.noSideEffect, procvar,
rtl, extern: "nsuNormalize".} = rtl, extern: "nsuNormalize".} =
## Normalizes the string `s`. That means to convert it to lower case and ## Normalizes the string `s`. That means to convert it to lower case and
## remove any '_'. This is needed for Nimrod identifiers for example. ## 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: for i in 0..len(s) - 1:
if s[i] in {'A'..'Z'}: 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] != '_': 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, proc cmpIgnoreCase*(a, b: string): int {.noSideEffect,
rtl, extern: "nsuCmpIgnoreCase", procvar.} = rtl, extern: "nsuCmpIgnoreCase", procvar.} =
@ -171,14 +175,14 @@ proc addf*(s: var string, formatstr: string, a: openarray[string]) {.
of '{': of '{':
var j = i+1 var j = i+1
while formatstr[j] notin {'\0', '}'}: inc(j) 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] if x >= 0 and x < high(a): add s, a[x+1]
else: raise newException(EInvalidValue, "invalid format string") else: raise newException(EInvalidValue, "invalid format string")
i = j+1 i = j+1
of 'a'..'z', 'A'..'Z', '\128'..'\255', '_': of 'a'..'z', 'A'..'Z', '\128'..'\255', '_':
var j = i+1 var j = i+1
while formatstr[j] in PatternChars: inc(j) 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] if x >= 0 and x < high(a): add s, a[x+1]
else: raise newException(EInvalidValue, "invalid format string") else: raise newException(EInvalidValue, "invalid format string")
i = j i = j
@ -226,13 +230,14 @@ proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect,
## ##
## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is ## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is
## raised if an ill-formed format string has been passed to the `%` operator. ## 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) addf(result, formatstr, a)
proc `%` *(formatstr, a: string): string {.noSideEffect, proc `%` *(formatstr, a: string): string {.noSideEffect,
rtl, extern: "nsuFormatSingleElem".} = rtl, extern: "nsuFormatSingleElem".} =
## This is the same as ``formatstr % [a]``. ## 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, proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect,
rtl, extern: "nsuStrip".} = rtl, extern: "nsuStrip".} =
@ -248,7 +253,7 @@ proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect,
while s[first] in chars: inc(first) while s[first] in chars: inc(first)
if trailing: if trailing:
while last >= 0 and s[last] in chars: dec(last) 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".} = proc toOctal*(c: char): string {.noSideEffect, rtl, extern: "nsuToOctal".} =
## Converts a character `c` to its octal representation. The resulting ## 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 var first = last
while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX! while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX!
if first <= last-1: if first <= last-1:
yield copy(s, first, last-1) yield substr(s, first, last-1)
iterator split*(s: string, sep: char): string = iterator split*(s: string, sep: char): string =
## Splits the string `s` into substrings. ## Splits the string `s` into substrings.
@ -321,7 +326,7 @@ iterator split*(s: string, sep: char): string =
while last <= len(s): while last <= len(s):
var first = last var first = last
while last < len(s) and s[last] != sep: inc(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) inc(last)
iterator splitLines*(s: string): string = iterator splitLines*(s: string): string =
@ -349,7 +354,7 @@ iterator splitLines*(s: string): string =
var last = 0 var last = 0
while true: while true:
while s[last] notin {'\0', '\c', '\l'}: inc(last) while s[last] notin {'\0', '\c', '\l'}: inc(last)
yield copy(s, first, last-1) yield substr(s, first, last-1)
# skip newlines: # skip newlines:
if s[last] == '\l': inc(last) if s[last] == '\l': inc(last)
elif s[last] == '\c': elif s[last] == '\c':
@ -499,7 +504,7 @@ iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[
var isSep = s[j] in seps var isSep = s[j] in seps
while j < s.len and (s[j] in seps) == isSep: inc(j) while j < s.len and (s[j] in seps) == isSep: inc(j)
if j > i: if j > i:
yield (copy(s, i, j-1), isSep) yield (substr(s, i, j-1), isSep)
else: else:
break break
i = j i = j
@ -510,19 +515,19 @@ proc wordWrap*(s: string, maxLineWidth = 80,
newLine = "\n"): string {. newLine = "\n"): string {.
noSideEffect, rtl, extern: "nsuWordWrap".} = noSideEffect, rtl, extern: "nsuWordWrap".} =
## word wraps `s`. ## word wraps `s`.
result = "" result = newStringOfCap(s.len + s.len shr 6)
var SpaceLeft = maxLineWidth var SpaceLeft = maxLineWidth
for word, isSep in tokenize(s, seps): for word, isSep in tokenize(s, seps):
if len(word) > SpaceLeft: if len(word) > SpaceLeft:
if splitLongWords and len(word) > maxLineWidth: 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 w = spaceLeft+1
var wordLeft = len(word) - spaceLeft var wordLeft = len(word) - spaceLeft
while wordLeft > 0: while wordLeft > 0:
result.add(newLine) result.add(newLine)
var L = min(maxLineWidth, wordLeft) var L = min(maxLineWidth, wordLeft)
SpaceLeft = maxLineWidth - L SpaceLeft = maxLineWidth - L
result.add(copy(word, w, w+L-1)) result.add(substr(word, w, w+L-1))
inc(w, L) inc(w, L)
dec(wordLeft, L) dec(wordLeft, L)
else: else:
@ -700,11 +705,11 @@ proc replace*(s, sub: string, by = ""): string {.noSideEffect,
while true: while true:
var j = findAux(s, sub, i, a) var j = findAux(s, sub, i, a)
if j < 0: break if j < 0: break
add result, copy(s, i, j - 1) add result, substr(s, i, j - 1)
add result, by add result, by
i = j + len(sub) i = j + len(sub)
# copy the rest: # copy the rest:
add result, copy(s, i) add result, substr(s, i)
proc replace*(s: string, sub, by: char): string {.noSideEffect, proc replace*(s: string, sub, by: char): string {.noSideEffect,
rtl, extern: "nsuReplaceChar".} = 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 ## The procedure has been designed so that its output is usable for many
## different common syntaxes. The resulting string is prefixed with ## different common syntaxes. The resulting string is prefixed with
## `prefix` and suffixed with `suffix`. Both may be empty strings. ## `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): for c in items(s):
case c case c
of '\0'..'\31', '\128'..'\255': 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) while s[i] in {'0'..'9', 'a'..'z', '-', '.'}: inc(i)
if s[i] != '\0': return false 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 if len(x) == 2 and x[0] in Letters and x[1] in Letters: return true
case toLower(x) case toLower(x)
of "com", "org", "net", "gov", "mil", "biz", "info", "mobi", "name", of "com", "org", "net", "gov", "mil", "biz", "info", "mobi", "name",

View file

@ -1021,9 +1021,9 @@ proc splitData*(TextNode: PText, offset: int): PText =
if offset > TextNode.data.len(): if offset > TextNode.data.len():
raise newException(EIndexSizeErr, "Index out of bounds") 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 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: if TextNode.FParentNode != nil:
for i in low(TextNode.FParentNode.childNodes)..high(TextNode.FParentNode.childNodes): for i in low(TextNode.FParentNode.childNodes)..high(TextNode.FParentNode.childNodes):

View file

@ -44,6 +44,10 @@ type
typeDesc* {.magic: TypeDesc.} ## meta type to denote typeDesc* {.magic: TypeDesc.} ## meta type to denote
## a type description (for templates) ## 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.} proc defined*[T](x: T): bool {.magic: "Defined", noSideEffect.}
## Special compile-time procedure that checks whether `x` is ## Special compile-time procedure that checks whether `x` is
## defined. `x` has to be an identifier or a qualified identifier. ## 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 ## content. One needs to fill the string character after character
## with the index operator ``s[i]``. This procedure exists only for ## with the index operator ``s[i]``. This procedure exists only for
## optimization purposes; the same effect can be achieved with the ## 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 {. proc `&` * (x: string, y: char): string {.
magic: "ConStrStr", noSideEffect, merge.} 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. # not be called explicitly! The user may decide to do this manually though.
proc copy*(s: string, first = 0): string {. 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 {. 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.} magic: "CopyStrLast", importc: "copyStrLast", noSideEffect.}
## copies a slice of `s` into a new string and returns this new ## copies a slice of `s` into a new string and returns this new
## string. The bounds `first` and `last` denote the indices of ## 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`. ## `op` to every item in `data`.
for i in 0..data.len-1: op(data[i]) 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 ## iterates over every field of `x`. Warning: This is really transforms
## the 'for' and unrolls the loop. The current implementation also has a bug ## the 'for' and unrolls the loop. The current implementation also has a bug
## that affects symbol binding in the loop body. ## 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.} magic: "Fields", noSideEffect.}
## iterates over every field of `x` and `y`. ## iterates over every field of `x` and `y`.
## Warning: This is really transforms the 'for' and unrolls the loop. ## Warning: This is really transforms the 'for' and unrolls the loop.
## The current implementation also has a bug that affects symbol binding ## The current implementation also has a bug that affects symbol binding
## in the loop body. ## 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 ## iterates over every field of `x`. Warning: This is really transforms
## the 'for' and unrolls the loop. The current implementation also has a bug ## the 'for' and unrolls the loop. The current implementation also has a bug
## that affects symbol binding in the loop body. ## 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.} magic: "FieldPairs", noSideEffect.}
## iterates over every field of `x` and `y`. ## iterates over every field of `x` and `y`.
## Warning: This is really transforms the 'for' and unrolls the loop. ## 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.} = proc `[]`*(s: string, x: TSlice[int]): string {.inline.} =
## slice operation for strings. Negative indexes are supported. ## 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) = proc `[]=`*(s: var string, x: TSlice[int], b: string) =
## slice assignment for strings. Negative indexes are supported. ## slice assignment for strings. Negative indexes are supported.

View file

@ -23,39 +23,50 @@ proc nimLoadLibraryError(path: string) {.compilerproc, noinline.}
proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline.} proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline.}
# Support for thread local storage: when false:
when defined(windows): # Support for thread local storage:
type when defined(windows):
TThreadVarSlot {.compilerproc.} = distinct int32 type
TThreadVarSlot {.compilerproc.} = distinct int32
proc TlsAlloc(): TThreadVarSlot {. proc TlsAlloc(): TThreadVarSlot {.
importc: "TlsAlloc", stdcall, dynlib: "kernel32".} importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
proc TlsSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {. proc TlsSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
importc: "TlsSetValue", stdcall, dynlib: "kernel32".} importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
proc TlsGetValue(dwTlsIndex: TThreadVarSlot): pointer {. proc TlsGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
importc: "TlsGetValue", stdcall, dynlib: "kernel32".} importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} = proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} =
result = TlsAlloc() result = TlsAlloc()
proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.compilerproc.} = proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.
TlsSetValue(s, value) compilerproc, inline.} =
proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.compilerproc.} = TlsSetValue(s, value)
result = TlsGetValue(s) proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.
compilerproc, inline.} =
else: result = TlsGetValue(s)
type
Tpthread_key {.importc: "pthread_key_t", else:
header: "<sys/types.h>".} = distinct int type
TThreadVarSlot {.compilerproc.} = Tpthread_key Tpthread_key {.importc: "pthread_key_t",
header: "<sys/types.h>".} = distinct int
TThreadVarSlot {.compilerproc.} = Tpthread_key
proc pthread_getspecific(a1: Tpthread_key): pointer {. proc pthread_getspecific(a1: Tpthread_key): pointer {.
importc: "pthread_getspecific", header: "<pthread.h>".} importc: "pthread_getspecific", header: "<pthread.h>".}
proc pthread_key_create(a1: ptr Tpthread_key, proc pthread_key_create(a1: ptr Tpthread_key,
destruct: proc (x: pointer) {.noconv.}): int32 {. destruct: proc (x: pointer) {.noconv.}): int32 {.
importc: "pthread_key_create", header: "<pthread.h>".} importc: "pthread_key_create", header: "<pthread.h>".}
proc pthread_key_delete(a1: Tpthread_key): int32 {. proc pthread_key_delete(a1: Tpthread_key): int32 {.
importc: "pthread_key_delete", header: "<pthread.h>".} importc: "pthread_key_delete", header: "<pthread.h>".}
proc pthread_setspecific(a1: Tpthread_key, a2: pointer): int32 {. proc pthread_setspecific(a1: Tpthread_key, a2: pointer): int32 {.
importc: "pthread_setspecific", header: "<pthread.h>".} 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)

View file

@ -39,6 +39,8 @@ type
exc: ref E_Base # XXX only needed for bootstrapping; unused exc: ref E_Base # XXX only needed for bootstrapping; unused
context: C_JmpBuf context: C_JmpBuf
#when hasThreadSupport: nil
var var
excHandler {.threadvar, compilerproc.}: PSafePoint = nil excHandler {.threadvar, compilerproc.}: PSafePoint = nil
# list of exception handlers # list of exception handlers

View file

@ -626,10 +626,23 @@ else:
# We use a jmp_buf buffer that is in the C stack. # We use a jmp_buf buffer that is in the C stack.
# Used to traverse the stack and registers assuming # Used to traverse the stack and registers assuming
# that 'setjmp' will save registers in the C stack. # that 'setjmp' will save registers in the C stack.
type PStackSlice = ptr array [0..7, pointer]
var registers: C_JmpBuf var registers: C_JmpBuf
if c_setjmp(registers) == 0'i32: # To fill the C stack with registers. if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
var max = cast[TAddress](stackBottom) var max = cast[TAddress](stackBottom)
var sp = cast[TAddress](addr(registers)) 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: while sp <=% max:
gcMark(cast[ppointer](sp)[]) gcMark(cast[ppointer](sp)[])
sp = sp +% sizeof(pointer) sp = sp +% sizeof(pointer)

View file

@ -111,7 +111,7 @@ type
TReprClosure {.final.} = object # we cannot use a global variable here TReprClosure {.final.} = object # we cannot use a global variable here
# as this wouldn't be thread-safe # as this wouldn't be thread-safe
marked: TCellSet marked: TCellSet
recdepth: int # do not recurse endless recdepth: int # do not recurse endlessly
indent: int # indentation indent: int # indentation
when not defined(useNimRtl): when not defined(useNimRtl):

View file

@ -8,8 +8,6 @@
# #
const const
hasThreadSupport = false # deactivate for now: thread stack walking
# is missing!
maxThreads = 256 maxThreads = 256
when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport: when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:

View file

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

View file

@ -15,7 +15,7 @@ import
lua, lualib, lauxlib, mysql, sqlite3, python, tcl, lua, lualib, lauxlib, mysql, sqlite3, python, tcl,
db_postgres, db_mysql, db_sqlite, ropes, sockets, browsers, httpserver, db_postgres, db_mysql, db_sqlite, ropes, sockets, browsers, httpserver,
httpclient, parseutils, unidecode, xmldom, xmldomparser, xmltree, xmlparser, httpclient, parseutils, unidecode, xmldom, xmldomparser, xmltree, xmlparser,
htmlparser, re, graphics, colors htmlparser, re, graphics, colors, pegs
when defined(linux): when defined(linux):
import import

View file

@ -1,6 +1,6 @@
* thread support: threadvar on Windows seems broken; * thread support: threadvar on Windows seems broken;
add --deadlock_prevention:on|off switch add --deadlock_prevention:on|off switch
- implicit ref/ptr->var conversion * implicit ref/ptr->var conversion
High priority (version 0.9.0) High priority (version 0.9.0)

View file

@ -31,6 +31,7 @@ Changes affecting backwards compatibility
priority. priority.
- Deprecated ``os.getApplicationFilename``: Use ``os.getAppFilename`` instead. - Deprecated ``os.getApplicationFilename``: Use ``os.getAppFilename`` instead.
- Deprecated ``os.getApplicationDir``: Use ``os.getAppDir`` 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 - Changed and documented how generalized string literals work: The syntax
``module.re"abc"`` is now supported. ``module.re"abc"`` is now supported.
- Changed the behaviour of ``strutils.%``, ``ropes.%`` - Changed the behaviour of ``strutils.%``, ``ropes.%``
@ -74,10 +75,11 @@ Additions
- Added the ``linearScanEnd``, ``unroll``, ``shallow`` pragmas. - Added the ``linearScanEnd``, ``unroll``, ``shallow`` pragmas.
- Added ``system.reset`` and a version of ``system.open`` that - Added ``system.reset`` and a version of ``system.open`` that
returns a ``TFile`` and raises an exception in case of an error. 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. on the number of string literals in the case statement.
- Added a wrapper for ``redis``. - Added a wrapper for ``redis``.
- The compiler now supports array, sequence and string slicing. - The compiler now supports array, sequence and string slicing.
- Added ``system.newStringOfCap``.
2010-10-20 Version 0.8.10 released 2010-10-20 Version 0.8.10 released