bugfix: multiple yield statements and loop body vars
This commit is contained in:
parent
e7fe8edab3
commit
63ac32e6de
13 changed files with 256 additions and 75 deletions
|
|
@ -226,20 +226,26 @@ proc push*(s: var TRunningStat, x: float) =
|
||||||
inc(s.n)
|
inc(s.n)
|
||||||
# See Knuth TAOCP vol 2, 3rd edition, page 232
|
# See Knuth TAOCP vol 2, 3rd edition, page 232
|
||||||
if s.n == 1:
|
if s.n == 1:
|
||||||
|
s.min = x
|
||||||
|
s.max = x
|
||||||
s.oldM = x
|
s.oldM = x
|
||||||
s.mean = x
|
s.mean = x
|
||||||
s.oldS = 0.0
|
s.oldS = 0.0
|
||||||
else:
|
else:
|
||||||
|
if s.min > x: s.min = x
|
||||||
|
if s.max < x: s.max = x
|
||||||
s.mean = s.oldM + (x - s.oldM)/toFloat(s.n)
|
s.mean = s.oldM + (x - s.oldM)/toFloat(s.n)
|
||||||
s.newS = s.oldS + (x - s.oldM)*(x - s.mean)
|
s.newS = s.oldS + (x - s.oldM)*(x - s.mean)
|
||||||
|
|
||||||
# set up for next iteration:
|
# set up for next iteration:
|
||||||
s.oldM = s.mean
|
s.oldM = s.mean
|
||||||
s.oldS = s.newS
|
s.oldS = s.newS
|
||||||
|
|
||||||
s.sum = s.sum + x
|
s.sum = s.sum + x
|
||||||
if s.min > x: s.min = x
|
|
||||||
if s.max < x: s.max = x
|
proc push*(s: var TRunningStat, x: int) =
|
||||||
|
## pushes a value `x` for processing. `x` is simply converted to ``float``
|
||||||
|
## and the other push operation is called.
|
||||||
|
push(s, toFloat(x))
|
||||||
|
|
||||||
proc variance*(s: TRunningStat): float =
|
proc variance*(s: TRunningStat): float =
|
||||||
## computes the current variance of `s`
|
## computes the current variance of `s`
|
||||||
|
|
|
||||||
|
|
@ -464,6 +464,69 @@ proc align*(s: string, count: int): string {.
|
||||||
else:
|
else:
|
||||||
result = s
|
result = s
|
||||||
|
|
||||||
|
iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[
|
||||||
|
token: string, isSep: bool] =
|
||||||
|
## Tokenizes the string `s` into substrings.
|
||||||
|
##
|
||||||
|
## Substrings are separated by a substring containing only `seps`.
|
||||||
|
## Examples:
|
||||||
|
##
|
||||||
|
## .. code-block:: nimrod
|
||||||
|
## for word in tokenize(" this is an example "):
|
||||||
|
## writeln(stdout, word)
|
||||||
|
##
|
||||||
|
## Results in:
|
||||||
|
##
|
||||||
|
## .. code-block:: nimrod
|
||||||
|
## (" ", true)
|
||||||
|
## ("this", false)
|
||||||
|
## (" ", true)
|
||||||
|
## ("is", false)
|
||||||
|
## (" ", true)
|
||||||
|
## ("an", false)
|
||||||
|
## (" ", true)
|
||||||
|
## ("example", false)
|
||||||
|
## (" ", true)
|
||||||
|
var i = 0
|
||||||
|
while true:
|
||||||
|
var j = i
|
||||||
|
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)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
i = j
|
||||||
|
|
||||||
|
proc wordWrap*(s: string, maxLineWidth = 80,
|
||||||
|
splitLongWords = true,
|
||||||
|
seps: set[char] = whitespace,
|
||||||
|
newLine = "\n"): string {.
|
||||||
|
noSideEffect, rtl, extern: "nsuWordWrap".} =
|
||||||
|
## word wraps `s`.
|
||||||
|
result = ""
|
||||||
|
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))
|
||||||
|
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))
|
||||||
|
inc(w, L)
|
||||||
|
dec(wordLeft, L)
|
||||||
|
else:
|
||||||
|
SpaceLeft = maxLineWidth - len(Word)
|
||||||
|
result.add(newLine)
|
||||||
|
result.add(word)
|
||||||
|
else:
|
||||||
|
SpaceLeft = SpaceLeft - len(Word)
|
||||||
|
result.add(word)
|
||||||
|
|
||||||
proc startsWith*(s, prefix: string): bool {.noSideEffect,
|
proc startsWith*(s, prefix: string): bool {.noSideEffect,
|
||||||
rtl, extern: "nsuStartsWith".} =
|
rtl, extern: "nsuStartsWith".} =
|
||||||
## Returns true iff ``s`` starts with ``prefix``.
|
## Returns true iff ``s`` starts with ``prefix``.
|
||||||
|
|
@ -879,6 +942,7 @@ when isMainModule:
|
||||||
assert align("abc", 4) == " abc"
|
assert align("abc", 4) == " abc"
|
||||||
assert align("a", 0) == "a"
|
assert align("a", 0) == "a"
|
||||||
assert align("1232", 6) == " 1232"
|
assert align("1232", 6) == " 1232"
|
||||||
|
echo wordWrap(""" this is a long text -- muchlongerthan10chars and here
|
||||||
|
it goes""", 10, false)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1099,6 +1099,15 @@ iterator items*(a: cstring): char {.inline.} =
|
||||||
yield a[i]
|
yield a[i]
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
|
iterator enumerate*[TContainer, TItem](a: TContainer): tuple[
|
||||||
|
index: int, item: TItem] {.inline.} =
|
||||||
|
## iterates over each item of `a` via `items` and yields an additional
|
||||||
|
## counter/index starting from 0.
|
||||||
|
var j = 0
|
||||||
|
for it in items(a):
|
||||||
|
yield (j, a)
|
||||||
|
inc j
|
||||||
|
|
||||||
proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil".}
|
proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil".}
|
||||||
proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
|
proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
|
||||||
proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil".}
|
proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil".}
|
||||||
|
|
@ -1108,20 +1117,20 @@ proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".}
|
||||||
## Fast check whether `x` is nil. This is sometimes more efficient than
|
## Fast check whether `x` is nil. This is sometimes more efficient than
|
||||||
## ``== nil``.
|
## ``== nil``.
|
||||||
|
|
||||||
proc `&` *[T](x, y: openArray[T]): seq[T] {.noSideEffect.} =
|
proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect.} =
|
||||||
newSeq(result, x.len + y.len)
|
newSeq(result, x.len + y.len)
|
||||||
for i in 0..x.len-1:
|
for i in 0..x.len-1:
|
||||||
result[i] = x[i]
|
result[i] = x[i]
|
||||||
for i in 0..y.len-1:
|
for i in 0..y.len-1:
|
||||||
result[i+x.len] = y[i]
|
result[i+x.len] = y[i]
|
||||||
|
|
||||||
proc `&` *[T](x: openArray[T], y: T): seq[T] {.noSideEffect.} =
|
proc `&` *[T](x: seq[T], y: T): seq[T] {.noSideEffect.} =
|
||||||
newSeq(result, x.len + 1)
|
newSeq(result, x.len + 1)
|
||||||
for i in 0..x.len-1:
|
for i in 0..x.len-1:
|
||||||
result[i] = x[i]
|
result[i] = x[i]
|
||||||
result[x.len] = y
|
result[x.len] = y
|
||||||
|
|
||||||
proc `&` *[T](x: T, y: openArray[T]): seq[T] {.noSideEffect.} =
|
proc `&` *[T](x: T, y: seq[T]): seq[T] {.noSideEffect.} =
|
||||||
newSeq(result, y.len + 1)
|
newSeq(result, y.len + 1)
|
||||||
for i in 0..y.len-1:
|
for i in 0..y.len-1:
|
||||||
result[i] = y[i]
|
result[i] = y[i]
|
||||||
|
|
|
||||||
34
rod/ast.nim
34
rod/ast.nim
|
|
@ -537,8 +537,8 @@ const
|
||||||
|
|
||||||
var gId*: int
|
var gId*: int
|
||||||
|
|
||||||
proc getID*(): int
|
proc getID*(): int {.inline.}
|
||||||
proc setID*(id: int)
|
proc setID*(id: int) {.inline.}
|
||||||
proc IDsynchronizationPoint*(idRange: int)
|
proc IDsynchronizationPoint*(idRange: int)
|
||||||
|
|
||||||
# creator procs:
|
# creator procs:
|
||||||
|
|
@ -568,10 +568,10 @@ proc copyStrTable*(dest: var TStrTable, src: TStrTable)
|
||||||
proc copyTable*(dest: var TTable, src: TTable)
|
proc copyTable*(dest: var TTable, src: TTable)
|
||||||
proc copyObjectSet*(dest: var TObjectSet, src: TObjectSet)
|
proc copyObjectSet*(dest: var TObjectSet, src: TObjectSet)
|
||||||
proc copyIdTable*(dest: var TIdTable, src: TIdTable)
|
proc copyIdTable*(dest: var TIdTable, src: TIdTable)
|
||||||
proc sonsLen*(n: PNode): int
|
proc sonsLen*(n: PNode): int {.inline.}
|
||||||
proc sonsLen*(n: PType): int
|
proc sonsLen*(n: PType): int {.inline.}
|
||||||
proc lastSon*(n: PNode): PNode
|
proc lastSon*(n: PNode): PNode {.inline.}
|
||||||
proc lastSon*(n: PType): PType
|
proc lastSon*(n: PType): PType {.inline.}
|
||||||
proc newSons*(father: PNode, length: int)
|
proc newSons*(father: PNode, length: int)
|
||||||
proc newSons*(father: PType, length: int)
|
proc newSons*(father: PType, length: int)
|
||||||
proc addSon*(father, son: PNode)
|
proc addSon*(father, son: PNode)
|
||||||
|
|
@ -903,6 +903,21 @@ proc copyNode(src: PNode): PNode =
|
||||||
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
|
proc shallowCopy*(src: PNode): PNode =
|
||||||
|
# does not copy its sons, but provides space for them:
|
||||||
|
if src == nil: return nil
|
||||||
|
result = newNode(src.kind)
|
||||||
|
result.info = src.info
|
||||||
|
result.typ = src.typ
|
||||||
|
result.flags = src.flags * PersistentNodeFlags
|
||||||
|
case src.Kind
|
||||||
|
of nkCharLit..nkInt64Lit: result.intVal = src.intVal
|
||||||
|
of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result.floatVal = src.floatVal
|
||||||
|
of nkSym: result.sym = src.sym
|
||||||
|
of nkIdent: result.ident = src.ident
|
||||||
|
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
||||||
|
else: newSons(result, sonsLen(src))
|
||||||
|
|
||||||
proc copyTree(src: PNode): PNode =
|
proc copyTree(src: PNode): PNode =
|
||||||
# copy a whole syntax tree; performs deep copying
|
# copy a whole syntax tree; performs deep copying
|
||||||
if src == nil:
|
if src == nil:
|
||||||
|
|
@ -920,7 +935,8 @@ proc copyTree(src: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
result.sons = nil
|
result.sons = nil
|
||||||
newSons(result, sonsLen(src))
|
newSons(result, sonsLen(src))
|
||||||
for i in countup(0, sonsLen(src) - 1): result.sons[i] = copyTree(src.sons[i])
|
for i in countup(0, sonsLen(src) - 1):
|
||||||
|
result.sons[i] = copyTree(src.sons[i])
|
||||||
|
|
||||||
proc lastSon(n: PNode): PNode =
|
proc lastSon(n: PNode): PNode =
|
||||||
result = n.sons[sonsLen(n) - 1]
|
result = n.sons[sonsLen(n) - 1]
|
||||||
|
|
@ -986,11 +1002,11 @@ proc getStrOrChar*(a: PNode): string =
|
||||||
internalError(a.info, "getStrOrChar")
|
internalError(a.info, "getStrOrChar")
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
proc mustRehash(length, counter: int): bool =
|
proc mustRehash(length, counter: int): bool {.inline.} =
|
||||||
assert(length > counter)
|
assert(length > counter)
|
||||||
result = (length * 2 < counter * 3) or (length - counter < 4)
|
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||||
|
|
||||||
proc nextTry(h, maxHash: THash): THash =
|
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
||||||
result = ((5 * h) + 1) and maxHash
|
result = ((5 * h) + 1) and maxHash
|
||||||
# For any initial h in range(maxHash), repeating that maxHash times
|
# For any initial h in range(maxHash), repeating that maxHash times
|
||||||
# generates each int in range(maxHash) exactly once (see any text on
|
# generates each int in range(maxHash) exactly once (see any text on
|
||||||
|
|
|
||||||
|
|
@ -767,15 +767,13 @@ proc IdNodeTableRawInsert(data: var TIdNodePairSeq, key: PIdObj, val: PNode) =
|
||||||
data[h].val = val
|
data[h].val = val
|
||||||
|
|
||||||
proc IdNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) =
|
proc IdNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) =
|
||||||
var
|
var index = IdNodeTableRawGet(t, key)
|
||||||
index: int
|
|
||||||
n: TIdNodePairSeq
|
|
||||||
index = IdNodeTableRawGet(t, key)
|
|
||||||
if index >= 0:
|
if index >= 0:
|
||||||
assert(t.data[index].key != nil)
|
assert(t.data[index].key != nil)
|
||||||
t.data[index].val = val
|
t.data[index].val = val
|
||||||
else:
|
else:
|
||||||
if mustRehash(len(t.data), t.counter):
|
if mustRehash(len(t.data), t.counter):
|
||||||
|
var n: TIdNodePairSeq
|
||||||
newSeq(n, len(t.data) * growthFactor)
|
newSeq(n, len(t.data) * growthFactor)
|
||||||
for i in countup(0, high(t.data)):
|
for i in countup(0, high(t.data)):
|
||||||
if t.data[i].key != nil:
|
if t.data[i].key != nil:
|
||||||
|
|
|
||||||
|
|
@ -14,20 +14,20 @@ type
|
||||||
TCandidateState = enum
|
TCandidateState = enum
|
||||||
csEmpty, csMatch, csNoMatch
|
csEmpty, csMatch, csNoMatch
|
||||||
TCandidate{.final.} = object
|
TCandidate{.final.} = object
|
||||||
exactMatches*: int
|
exactMatches: int
|
||||||
subtypeMatches*: int
|
subtypeMatches: int
|
||||||
intConvMatches*: int # conversions to int are not as expensive
|
intConvMatches: int # conversions to int are not as expensive
|
||||||
convMatches*: int
|
convMatches: int
|
||||||
genericMatches*: int
|
genericMatches: int
|
||||||
state*: TCandidateState
|
state: TCandidateState
|
||||||
callee*: PType # may not be nil!
|
callee: PType # may not be nil!
|
||||||
calleeSym*: PSym # may be nil
|
calleeSym: PSym # may be nil
|
||||||
call*: PNode # modified call
|
call: PNode # modified call
|
||||||
bindings*: TIdTable # maps sym-ids to types
|
bindings: TIdTable # maps sym-ids to types
|
||||||
baseTypeMatch*: bool # needed for conversions from T to openarray[T]
|
baseTypeMatch: bool # needed for conversions from T to openarray[T]
|
||||||
# for example
|
# for example
|
||||||
|
|
||||||
TTypeRelation = enum # order is important!
|
TTypeRelation = enum # order is important!
|
||||||
isNone, isConvertible, isIntConv, isSubtype, isGeneric, isEqual
|
isNone, isConvertible, isIntConv, isSubtype, isGeneric, isEqual
|
||||||
|
|
||||||
proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} =
|
proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} =
|
||||||
|
|
|
||||||
108
rod/transf.nim
108
rod/transf.nim
|
|
@ -29,20 +29,23 @@ proc transfPass*(): TPass
|
||||||
type
|
type
|
||||||
PTransCon = ref TTransCon
|
PTransCon = ref TTransCon
|
||||||
TTransCon{.final.} = object # part of TContext; stackable
|
TTransCon{.final.} = object # part of TContext; stackable
|
||||||
mapping*: TIdNodeTable # mapping from symbols to nodes
|
mapping: TIdNodeTable # mapping from symbols to nodes
|
||||||
owner*: PSym # current owner
|
owner: PSym # current owner
|
||||||
forStmt*: PNode # current for stmt
|
forStmt: PNode # current for stmt
|
||||||
next*: PTransCon # for stacking
|
next: PTransCon # for stacking
|
||||||
|
|
||||||
TTransfContext = object of passes.TPassContext
|
TTransfContext = object of passes.TPassContext
|
||||||
module*: PSym
|
module: PSym
|
||||||
transCon*: PTransCon # top of a TransCon stack
|
transCon: PTransCon # top of a TransCon stack
|
||||||
|
inlining: int # > 0 if we are in inlining context (copy vars)
|
||||||
|
|
||||||
PTransf = ref TTransfContext
|
PTransf = ref TTransfContext
|
||||||
|
|
||||||
proc newTransCon(): PTransCon =
|
proc newTransCon(owner: PSym): PTransCon =
|
||||||
|
assert owner != nil
|
||||||
new(result)
|
new(result)
|
||||||
initIdNodeTable(result.mapping)
|
initIdNodeTable(result.mapping)
|
||||||
|
result.owner = owner
|
||||||
|
|
||||||
proc pushTransCon(c: PTransf, t: PTransCon) =
|
proc pushTransCon(c: PTransf, t: PTransCon) =
|
||||||
t.next = c.transCon
|
t.next = c.transCon
|
||||||
|
|
@ -209,9 +212,50 @@ proc transformYield(c: PTransf, n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
e = transform(c, copyTree(e))
|
e = transform(c, copyTree(e))
|
||||||
addSon(result, newAsgnStmt(c, c.transCon.forStmt.sons[0], e))
|
addSon(result, newAsgnStmt(c, c.transCon.forStmt.sons[0], e))
|
||||||
|
|
||||||
|
#var tc = newTransCon(c.transCon.owner)
|
||||||
|
#tc.forStmt = c.transCon.forStmt
|
||||||
|
#pushTransCon(c, tc)
|
||||||
|
inc(c.inlining)
|
||||||
addSon(result, transform(c, lastSon(c.transCon.forStmt)))
|
addSon(result, transform(c, lastSon(c.transCon.forStmt)))
|
||||||
|
dec(c.inlining)
|
||||||
|
#popTransCon(c)
|
||||||
|
|
||||||
|
proc transformVarSection(c: PTransf, v: PNode): PNode =
|
||||||
|
result = copyTree(v)
|
||||||
|
for i in countup(0, sonsLen(result) - 1):
|
||||||
|
var it = result.sons[i]
|
||||||
|
if it.kind == nkCommentStmt: continue
|
||||||
|
if it.kind == nkIdentDefs:
|
||||||
|
if (it.sons[0].kind != nkSym):
|
||||||
|
InternalError(it.info, "transformVarSection")
|
||||||
|
var newVar = copySym(it.sons[0].sym)
|
||||||
|
if identEq(newVar.name, "titer2TestVar"):
|
||||||
|
echo "created a copy of titer2TestVar ", newVar.id, " ",
|
||||||
|
it.sons[0].sym.id
|
||||||
|
|
||||||
|
incl(newVar.flags, sfFromGeneric)
|
||||||
|
# fixes a strange bug for rodgen:
|
||||||
|
#include(it.sons[0].sym.flags, sfFromGeneric);
|
||||||
|
newVar.owner = getCurrOwner(c)
|
||||||
|
IdNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar))
|
||||||
|
it.sons[0].sym = newVar
|
||||||
|
it.sons[2] = transform(c, it.sons[2])
|
||||||
|
else:
|
||||||
|
if it.kind != nkVarTuple:
|
||||||
|
InternalError(it.info, "transformVarSection: not nkVarTuple")
|
||||||
|
var L = sonsLen(it)
|
||||||
|
for j in countup(0, L - 3):
|
||||||
|
var newVar = copySym(it.sons[j].sym)
|
||||||
|
incl(newVar.flags, sfFromGeneric)
|
||||||
|
newVar.owner = getCurrOwner(c)
|
||||||
|
IdNodeTablePut(c.transCon.mapping, it.sons[j].sym, newSymNode(newVar))
|
||||||
|
it.sons[j] = newSymNode(newVar)
|
||||||
|
assert(it.sons[L - 2] == nil)
|
||||||
|
it.sons[L - 1] = transform(c, it.sons[L - 1])
|
||||||
|
|
||||||
proc inlineIter(c: PTransf, n: PNode): PNode =
|
proc inlineIter(c: PTransf, n: PNode): PNode =
|
||||||
|
# n: iterator body
|
||||||
result = n
|
result = n
|
||||||
if n == nil: return
|
if n == nil: return
|
||||||
case n.kind
|
case n.kind
|
||||||
|
|
@ -220,32 +264,7 @@ proc inlineIter(c: PTransf, n: PNode): PNode =
|
||||||
of nkYieldStmt:
|
of nkYieldStmt:
|
||||||
result = transformYield(c, n)
|
result = transformYield(c, n)
|
||||||
of nkVarSection:
|
of nkVarSection:
|
||||||
result = copyTree(n)
|
result = transformVarSection(c, n)
|
||||||
for i in countup(0, sonsLen(result) - 1):
|
|
||||||
var it = result.sons[i]
|
|
||||||
if it.kind == nkCommentStmt: continue
|
|
||||||
if it.kind == nkIdentDefs:
|
|
||||||
if (it.sons[0].kind != nkSym): InternalError(it.info, "inlineIter")
|
|
||||||
var newVar = copySym(it.sons[0].sym)
|
|
||||||
incl(newVar.flags, sfFromGeneric)
|
|
||||||
# fixes a strange bug for rodgen:
|
|
||||||
#include(it.sons[0].sym.flags, sfFromGeneric);
|
|
||||||
newVar.owner = getCurrOwner(c)
|
|
||||||
IdNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar))
|
|
||||||
it.sons[0] = newSymNode(newVar)
|
|
||||||
it.sons[2] = transform(c, it.sons[2])
|
|
||||||
else:
|
|
||||||
if it.kind != nkVarTuple:
|
|
||||||
InternalError(it.info, "inlineIter: not nkVarTuple")
|
|
||||||
var L = sonsLen(it)
|
|
||||||
for j in countup(0, L - 3):
|
|
||||||
var newVar = copySym(it.sons[j].sym)
|
|
||||||
incl(newVar.flags, sfFromGeneric)
|
|
||||||
newVar.owner = getCurrOwner(c)
|
|
||||||
IdNodeTablePut(c.transCon.mapping, it.sons[j].sym, newSymNode(newVar))
|
|
||||||
it.sons[j] = newSymNode(newVar)
|
|
||||||
assert(it.sons[L - 2] == nil)
|
|
||||||
it.sons[L - 1] = transform(c, it.sons[L - 1])
|
|
||||||
else:
|
else:
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
for i in countup(0, sonsLen(n) - 1): addSon(result, inlineIter(c, n.sons[i]))
|
for i in countup(0, sonsLen(n) - 1): addSon(result, inlineIter(c, n.sons[i]))
|
||||||
|
|
@ -388,11 +407,11 @@ proc transformFor(c: PTransf, n: PNode): PNode =
|
||||||
for i in countup(0, length - 3):
|
for i in countup(0, length - 3):
|
||||||
addVar(v, copyTree(n.sons[i])) # declare new vars
|
addVar(v, copyTree(n.sons[i])) # declare new vars
|
||||||
addSon(result, v)
|
addSon(result, v)
|
||||||
var newC = newTransCon()
|
|
||||||
var call = n.sons[length - 2]
|
var call = n.sons[length - 2]
|
||||||
if (call.kind != nkCall) or (call.sons[0].kind != nkSym):
|
if (call.kind != nkCall) or (call.sons[0].kind != nkSym):
|
||||||
InternalError(call.info, "transformFor")
|
InternalError(call.info, "transformFor")
|
||||||
newC.owner = call.sons[0].sym
|
|
||||||
|
var newC = newTransCon(call.sons[0].sym)
|
||||||
newC.forStmt = n
|
newC.forStmt = n
|
||||||
if (newC.owner.kind != skIterator):
|
if (newC.owner.kind != skIterator):
|
||||||
InternalError(call.info, "transformFor")
|
InternalError(call.info, "transformFor")
|
||||||
|
|
@ -486,7 +505,7 @@ proc transformLambda(c: PTransf, n: PNode): PNode =
|
||||||
# all variables that are accessed should be accessed by the new closure
|
# all variables that are accessed should be accessed by the new closure
|
||||||
# parameter:
|
# parameter:
|
||||||
if sonsLen(closure) > 0:
|
if sonsLen(closure) > 0:
|
||||||
var newC = newTransCon()
|
var newC = newTransCon(c.transCon.owner)
|
||||||
for i in countup(0, sonsLen(closure) - 1):
|
for i in countup(0, sonsLen(closure) - 1):
|
||||||
IdNodeTablePut(newC.mapping, closure.sons[i].sym,
|
IdNodeTablePut(newC.mapping, closure.sons[i].sym,
|
||||||
indirectAccess(param, closure.sons[i].sym))
|
indirectAccess(param, closure.sons[i].sym))
|
||||||
|
|
@ -613,22 +632,35 @@ proc transform(c: PTransf, n: PNode): PNode =
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||||
result = transformConv(c, n)
|
result = transformConv(c, n)
|
||||||
of nkDiscardStmt:
|
of nkDiscardStmt:
|
||||||
for i in countup(0, sonsLen(n) - 1): result.sons[i] = transform(c, n.sons[i])
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
|
result.sons[i] = transform(c, n.sons[i])
|
||||||
if isConstExpr(result.sons[0]): result = newNode(nkCommentStmt)
|
if isConstExpr(result.sons[0]): result = newNode(nkCommentStmt)
|
||||||
of nkCommentStmt, nkTemplateDef:
|
of nkCommentStmt, nkTemplateDef:
|
||||||
return
|
return
|
||||||
of nkConstSection:
|
of nkConstSection:
|
||||||
# do not replace ``const c = 3`` with ``const 3 = 3``
|
# do not replace ``const c = 3`` with ``const 3 = 3``
|
||||||
return
|
return
|
||||||
|
of nkVarSection:
|
||||||
|
if c.inlining > 0:
|
||||||
|
# we need to copy the variables for multiple yield statements:
|
||||||
|
result = transformVarSection(c, n)
|
||||||
|
else:
|
||||||
|
result = shallowCopy(n)
|
||||||
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
|
result.sons[i] = transform(c, n.sons[i])
|
||||||
else:
|
else:
|
||||||
for i in countup(0, sonsLen(n) - 1): result.sons[i] = transform(c, n.sons[i])
|
result = shallowCopy(n)
|
||||||
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
|
result.sons[i] = transform(c, n.sons[i])
|
||||||
var cnst = getConstExpr(c.module, result)
|
var cnst = getConstExpr(c.module, result)
|
||||||
if cnst != nil:
|
if cnst != nil:
|
||||||
result = cnst # do not miss an optimization
|
result = cnst # do not miss an optimization
|
||||||
|
|
||||||
proc processTransf(context: PPassContext, n: PNode): PNode =
|
proc processTransf(context: PPassContext, n: PNode): PNode =
|
||||||
var c = PTransf(context)
|
var c = PTransf(context)
|
||||||
|
pushTransCon(c, newTransCon(getCurrOwner(c)))
|
||||||
result = transform(c, n)
|
result = transform(c, n)
|
||||||
|
popTransCon(c)
|
||||||
|
|
||||||
proc openTransf(module: PSym, filename: string): PPassContext =
|
proc openTransf(module: PSym, filename: string): PPassContext =
|
||||||
var n: PTransf
|
var n: PTransf
|
||||||
|
|
|
||||||
18
tests/accept/compile/toop.nim
Normal file
18
tests/accept/compile/toop.nim
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
type
|
||||||
|
TA = object
|
||||||
|
x, y: int
|
||||||
|
|
||||||
|
TB = object of TA
|
||||||
|
z: int
|
||||||
|
|
||||||
|
TC = object of TB
|
||||||
|
whatever: string
|
||||||
|
|
||||||
|
proc p(a: var TA) = nil
|
||||||
|
proc p(b: var TB) = nil
|
||||||
|
|
||||||
|
var c: TC
|
||||||
|
|
||||||
|
p(c)
|
||||||
|
|
||||||
|
|
@ -9,7 +9,9 @@ proc QuickSort(list: seq[int]): seq[int] =
|
||||||
left.add(list[i])
|
left.add(list[i])
|
||||||
elif list[i] > pivot:
|
elif list[i] > pivot:
|
||||||
right.add(list[i])
|
right.add(list[i])
|
||||||
result = QuickSort(left) & pivot & QuickSort(right)
|
result = QuickSort(left) &
|
||||||
|
pivot &
|
||||||
|
QuickSort(right)
|
||||||
|
|
||||||
proc echoSeq(a: seq[int]) =
|
proc echoSeq(a: seq[int]) =
|
||||||
for i in low(a)..high(a):
|
for i in low(a)..high(a):
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ tisopr.nim;falsetrue
|
||||||
titer2.nim;123
|
titer2.nim;123
|
||||||
titer3.nim;1231
|
titer3.nim;1231
|
||||||
titer5.nim;abcxyz
|
titer5.nim;abcxyz
|
||||||
|
titer6.nim;000
|
||||||
tlenopenarray.nim;1
|
tlenopenarray.nim;1
|
||||||
tlowhigh.nim;10
|
tlowhigh.nim;10
|
||||||
tmatrix.nim;111
|
tmatrix.nim;111
|
||||||
|
|
|
||||||
|
31
tests/accept/run/titer6.nim
Normal file
31
tests/accept/run/titer6.nim
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Test iterator with more than 1 yield statement
|
||||||
|
|
||||||
|
import strutils
|
||||||
|
|
||||||
|
iterator tokenize2(s: string, seps: set[char] = Whitespace): tuple[
|
||||||
|
token: string, isSep: bool] =
|
||||||
|
var i = 0
|
||||||
|
while i < s.len:
|
||||||
|
var j = i
|
||||||
|
if s[j] in seps:
|
||||||
|
while j < s.len and s[j] in seps: inc(j)
|
||||||
|
if j > i:
|
||||||
|
yield (copy(s, i, j-1), true)
|
||||||
|
else:
|
||||||
|
while j < s.len and s[j] notin seps: inc(j)
|
||||||
|
if j > i:
|
||||||
|
yield (copy(s, i, j-1), false)
|
||||||
|
i = j
|
||||||
|
|
||||||
|
for word, isSep in tokenize2("ta da", whiteSpace):
|
||||||
|
var titer2TestVar = 0
|
||||||
|
stdout.write(titer2TestVar)
|
||||||
|
|
||||||
|
proc wordWrap2(s: string, maxLineWidth = 80,
|
||||||
|
splitLongWords = true,
|
||||||
|
seps: set[char] = whitespace,
|
||||||
|
newLine = "\n"): string =
|
||||||
|
result = ""
|
||||||
|
for word, isSep in tokenize2(s, seps):
|
||||||
|
var w = 0
|
||||||
|
|
||||||
2
todo.txt
2
todo.txt
|
|
@ -1,6 +1,8 @@
|
||||||
High priority (version 0.9.0)
|
High priority (version 0.9.0)
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
|
- transf should use distinct types; shallowCopy() for PNode
|
||||||
|
|
||||||
- fix implicit generic routines
|
- fix implicit generic routines
|
||||||
- fix the streams implementation so that it uses methods
|
- fix the streams implementation so that it uses methods
|
||||||
- fix overloading resolution
|
- fix overloading resolution
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ Bugfixes
|
||||||
- Bugfix: ``dialogs.ChooseFilesToOpen`` did not work if only one file is
|
- Bugfix: ``dialogs.ChooseFilesToOpen`` did not work if only one file is
|
||||||
selected.
|
selected.
|
||||||
- Bugfix: niminst: ``nimrod`` is not default dir for *every* project.
|
- Bugfix: niminst: ``nimrod`` is not default dir for *every* project.
|
||||||
|
- Bugfix: Multiple yield statements in iterators did not cause local vars to be
|
||||||
|
copied.
|
||||||
|
|
||||||
|
|
||||||
Additions
|
Additions
|
||||||
|
|
@ -23,7 +25,7 @@ Additions
|
||||||
|
|
||||||
- Added ``re.findAll``, ``pegs.findAll``.
|
- Added ``re.findAll``, ``pegs.findAll``.
|
||||||
- Added ``os.findExe``.
|
- Added ``os.findExe``.
|
||||||
- Added ``strutils.align``.
|
- Added ``strutils.align``, ``strutils.tokenize``, ``strutils.wordWrap``.
|
||||||
- Pegs support a *captured search loop operator* ``{@}``.
|
- Pegs support a *captured search loop operator* ``{@}``.
|
||||||
- Pegs support new built-ins: ``\letter``, ``\upper``, ``\lower``,
|
- Pegs support new built-ins: ``\letter``, ``\upper``, ``\lower``,
|
||||||
``\title``, ``\white``.
|
``\title``, ``\white``.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue