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

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

View File

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

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,
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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

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
# 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:

View File

@@ -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:

View File

@@ -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]) =

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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
------------------- ------------ --------------------------------------

View File

@@ -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.

View File

@@ -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 ``&gt;``
## * ``&`` is replaced by ``&amp;``
## * 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

View File

@@ -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 ';'

View File

@@ -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")

View File

@@ -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).

View File

@@ -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:

View File

@@ -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)

View File

@@ -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.

View File

@@ -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:

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 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

View File

@@ -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

View File

@@ -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".} =

View File

@@ -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])

View File

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

View File

@@ -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):

View File

@@ -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.

View File

@@ -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
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.} =
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 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_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 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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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):

View File

@@ -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:

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,
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

View File

@@ -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)

View File

@@ -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