diff options
-rw-r--r-- | compiler/lambdalifting.nim | 3 | ||||
-rw-r--r-- | compiler/transf.nim | 10 | ||||
-rw-r--r-- | tests/iter/tpermutations.nim | 58 |
3 files changed, 70 insertions, 1 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 3dd116078..20f903da9 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -213,6 +213,8 @@ proc makeClosure*(prc: PSym; env: PNode; info: TLineInfo): PNode = if env == nil: result.add(newNodeIT(nkNilLit, info, getSysType(tyNil))) else: + if env.kind == nkClosure: + localError(info, "internal error: taking closure of closure") result.add(env) proc interestingIterVar(s: PSym): bool {.inline.} = @@ -709,6 +711,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass; of nkClosure: if n[1].kind == nkNilLit: n.sons[0] = liftCapturedVars(n[0], owner, d, c) + #if n.sons[0].kind == nkClosure: result = n.sons[0] of nkLambdaKinds, nkIteratorDef: if n.typ != nil and n[namePos].kind == nkSym: let m = newSymNode(n[namePos].sym) diff --git a/compiler/transf.nim b/compiler/transf.nim index 296ea0a0d..50db2c7e8 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -313,10 +313,18 @@ proc introduceNewLocalVars(c: PTransf, n: PNode): PTransNode = result = PTransNode(n) of nkVarSection, nkLetSection: result = transformVarSection(c, n) + of nkClosure: + # it can happen that for-loop-inlining produced a fresh + # set of variables, including some computed environment + # (bug #2604). We need to patch this environment here too: + let a = n[1] + if a.kind == nkSym: + n.sons[1] = transformSymAux(c, a) + return PTransNode(n) else: result = newTransNode(n) for i in countup(0, sonsLen(n)-1): - result[i] = introduceNewLocalVars(c, n.sons[i]) + result[i] = introduceNewLocalVars(c, n.sons[i]) proc transformYield(c: PTransf, n: PNode): PTransNode = result = newTransNode(nkStmtList, n.info, 0) diff --git a/tests/iter/tpermutations.nim b/tests/iter/tpermutations.nim new file mode 100644 index 000000000..a3b383323 --- /dev/null +++ b/tests/iter/tpermutations.nim @@ -0,0 +1,58 @@ + +import sequtils, future + +iterator permutations*[T](ys: openarray[T]): tuple[perm: seq[T], sign: int] = + var + d = 1 + c = newSeq[int](ys.len) + xs = newSeq[T](ys.len) + sign = 1 + + for i, y in ys: xs[i] = y + yield (xs, sign) + + block outter: + while true: + while d > 1: + dec d + c[d] = 0 + while c[d] >= d: + inc d + if d >= ys.len: break outter + + let i = if (d and 1) == 1: c[d] else: 0 + swap xs[i], xs[d] + sign *= -1 + yield (xs, sign) + inc c[d] + +proc det(a: seq[seq[float]]): float = + let n = toSeq 0..a.high + for sigma, sign in n.permutations: + result += sign.float * n.map((i: int) => a[i][sigma[i]]).foldl(a * b) + +proc perm(a: seq[seq[float]]): float = + let n = toSeq 0..a.high + for sigma, sign in n.permutations: + result += n.map((i: int) => a[i][sigma[i]]).foldl(a * b) + +for a in [ + @[ @[1.0, 2.0] + , @[3.0, 4.0] + ], + @[ @[ 1.0, 2, 3, 4] + , @[ 4.0, 5, 6, 7] + , @[ 7.0, 8, 9, 10] + , @[10.0, 11, 12, 13] + ], + @[ @[ 0.0, 1, 2, 3, 4] + , @[ 5.0, 6, 7, 8, 9] + , @[10.0, 11, 12, 13, 14] + , @[15.0, 16, 17, 18, 19] + , @[20.0, 21, 22, 23, 24] + ] ]: + echo a + echo "perm: ", a.perm, " det: ", a.det + +# bug #3499 last snippet fixed +# bug 705 last snippet fixed |