diff options
author | Araq <rumpf_a@web.de> | 2015-03-12 00:27:49 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2015-03-12 01:45:14 +0100 |
commit | 5a21892da0d16cc0fb321dadb17140a4808b0c17 (patch) | |
tree | a40eae85e4182999eb3f60525ffed1b823b62dd8 | |
parent | 970e98718dfe0c494369bcb42b12d8cf7ace3f7c (diff) | |
download | Nim-5a21892da0d16cc0fb321dadb17140a4808b0c17.tar.gz |
fixes #2287
-rw-r--r-- | compiler/guards.nim | 104 | ||||
-rw-r--r-- | compiler/renderer.nim | 474 | ||||
-rw-r--r-- | compiler/semparallel.nim | 4 | ||||
-rw-r--r-- | compiler/transf.nim | 1 | ||||
-rw-r--r-- | tests/parallel/tsimple_array_checks.nim | 41 | ||||
-rw-r--r-- | todo.txt | 1 |
6 files changed, 345 insertions, 280 deletions
diff --git a/compiler/guards.nim b/compiler/guards.nim index 3255364c2..b0420cb75 100644 --- a/compiler/guards.nim +++ b/compiler/guards.nim @@ -15,11 +15,11 @@ import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer, idents, const someEq = {mEqI, mEqI64, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc, mEqUntracedRef, mEqStr, mEqSet, mEqCString} - + # set excluded here as the semantics are vastly different: someLe = {mLeI, mLeI64, mLeF64, mLeU, mLeU64, mLeEnum, mLeCh, mLeB, mLePtr, mLeStr} - someLt = {mLtI, mLtI64, mLtF64, mLtU, mLtU64, mLtEnum, + someLt = {mLtI, mLtI64, mLtF64, mLtU, mLtU64, mLtEnum, mLtCh, mLtB, mLtPtr, mLtStr} someLen = {mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq} @@ -44,7 +44,7 @@ proc isLet(n: PNode): bool = if n.kind == nkSym: if n.sym.kind in {skLet, skTemp, skForVar}: result = true - elif n.sym.kind == skParam and skipTypes(n.sym.typ, + elif n.sym.kind == skParam and skipTypes(n.sym.typ, abstractInst).kind != tyVar: result = true @@ -117,7 +117,7 @@ proc neg(n: PNode): PNode = result.sons[0] = n.sons[0] result.sons[2] = n.sons[2] if t.kind == tyEnum: - var s = newNodeIT(nkCurly, n.info, n.sons[1].typ) + var s = newNodeIT(nkCurly, n.info, n.sons[1].typ) for e in t.n: let eAsNode = newIntNode(nkIntLit, e.sym.position) if not inSet(n.sons[1], eAsNode): s.add eAsNode @@ -189,13 +189,17 @@ proc zero(): PNode = nkIntLit.newIntNode(0) proc one(): PNode = nkIntLit.newIntNode(1) proc minusOne(): PNode = nkIntLit.newIntNode(-1) -proc lowBound*(x: PNode): PNode = +proc lowBound*(x: PNode): PNode = result = nkIntLit.newIntNode(firstOrd(x.typ)) result.info = x.info proc highBound*(x: PNode): PNode = - result = if x.typ.skipTypes(abstractInst).kind == tyArray: - nkIntLit.newIntNode(lastOrd(x.typ)) + let typ = x.typ.skipTypes(abstractInst) + result = if typ.kind in {tyArrayConstr, tyArray}: + nkIntLit.newIntNode(lastOrd(typ)) + elif typ.kind == tySequence and x.kind == nkSym and + x.sym.kind == skConst: + nkIntLit.newIntNode(x.sym.ast.len-1) else: opAdd.buildCall(opLen.buildCall(x), minusOne()) result.info = x.info @@ -205,21 +209,32 @@ proc reassociation(n: PNode): PNode = # (foo+5)+5 --> foo+10; same for '*' case result.getMagic of someAdd: - if result[2].isValue and + if result[2].isValue and result[1].getMagic in someAdd and result[1][2].isValue: result = opAdd.buildCall(result[1][1], result[1][2] |+| result[2]) of someMul: - if result[2].isValue and + if result[2].isValue and result[1].getMagic in someMul and result[1][2].isValue: result = opAdd.buildCall(result[1][1], result[1][2] |*| result[2]) else: discard +proc pred(n: PNode): PNode = + if n.kind in {nkCharLit..nkUInt64Lit} and n.intVal != low(BiggestInt): + result = copyNode(n) + dec result.intVal + else: + result = n + proc canon*(n: PNode): PNode = # XXX for now only the new code in 'semparallel' uses this if n.safeLen >= 1: result = shallowCopy(n) for i in 0 .. < n.len: result.sons[i] = canon(n.sons[i]) + elif n.kind == nkSym and n.sym.kind == skLet and + n.sym.ast.getMagic in (someEq + someAdd + someMul + someMin + + someMax + someHigh + {mUnaryLt} + someSub + someLen): + result = n.sym.ast.copyTree else: result = n case result.getMagic @@ -231,34 +246,40 @@ proc canon*(n: PNode): PNode = of someHigh: # high == len+(-1) result = opAdd.buildCall(opLen.buildCall(result[1]), minusOne()) - of mUnaryMinusI, mUnaryMinusI64: + of mUnaryLt: result = buildCall(opAdd, result[1], newIntNode(nkIntLit, -1)) of someSub: # x - 4 --> x + (-4) result = negate(result[1], result[2], result) of someLen: result.sons[0] = opLen.newSymNode + of someLt: + # x < y same as x <= y-1: + let y = n[2].canon + let p = pred(y) + let minus = if p != y: p else: opAdd.buildCall(y, minusOne()).canon + result = opLe.buildCall(n[1].canon, minus) else: discard result = skipConv(result) result = reassociation(result) - # most important rule: (x-4) < a.len --> x < a.len+4 + # most important rule: (x-4) <= a.len --> x <= a.len+4 case result.getMagic - of someLe, someLt: + of someLe: let x = result[1] let y = result[2] - if x.kind in nkCallKinds and x.len == 3 and x[2].isValue and + if x.kind in nkCallKinds and x.len == 3 and x[2].isValue and isLetLocation(x[1], true): case x.getMagic of someSub: - result = buildCall(result[0].sym, x[1], + result = buildCall(result[0].sym, x[1], reassociation(opAdd.buildCall(y, x[2]))) of someAdd: # Rule A: let plus = negate(y, x[2], nil).reassociation if plus != nil: result = buildCall(result[0].sym, x[1], plus) else: discard - elif y.kind in nkCallKinds and y.len == 3 and y[2].isValue and + elif y.kind in nkCallKinds and y.len == 3 and y[2].isValue and isLetLocation(y[1], true): # a.len < x-3 case y.getMagic @@ -317,7 +338,7 @@ proc usefulFact(n: PNode): PNode = of mOr: # 'or' sucks! (p.isNil or q.isNil) --> hard to do anything # with that knowledge... - # DeMorgan helps a little though: + # DeMorgan helps a little though: # not a or not b --> not (a and b) # (x == 3) or (y == 2) ---> not ( not (x==3) and not (y == 2)) # not (x != 3 and y != 2) @@ -348,11 +369,11 @@ proc addFact*(m: var TModel, n: PNode) = let n = usefulFact(n) if n != nil: m.add n -proc addFactNeg*(m: var TModel, n: PNode) = +proc addFactNeg*(m: var TModel, n: PNode) = let n = n.neg if n != nil: addFact(m, n) -proc sameTree*(a, b: PNode): bool = +proc sameTree*(a, b: PNode): bool = result = false if a == b: result = true @@ -382,8 +403,8 @@ proc invalidateFacts*(m: var TModel, n: PNode) = # 'while p != nil: f(p); p = p.next' # This is actually quite easy to do: # Re-assignments (incl. pass to a 'var' param) trigger an invalidation - # of every fact that contains 'v'. - # + # of every fact that contains 'v'. + # # if x < 4: # if y < 5 # x = unknown() @@ -402,16 +423,9 @@ proc valuesUnequal(a, b: PNode): bool = if a.isValue and b.isValue: result = not sameValue(a, b) -proc pred(n: PNode): PNode = - if n.kind in {nkCharLit..nkUInt64Lit} and n.intVal != low(BiggestInt): - result = copyNode(n) - dec result.intVal - else: - result = n - proc impliesEq(fact, eq: PNode): TImplication = let (loc, val) = if isLocation(eq.sons[1]): (1, 2) else: (2, 1) - + case fact.sons[0].sym.magic of someEq: if sameTree(fact.sons[1], eq.sons[loc]): @@ -428,12 +442,12 @@ proc impliesEq(fact, eq: PNode): TImplication = else: result = impNo of mNot, mOr, mAnd: internalError(eq.info, "impliesEq") else: discard - + proc leImpliesIn(x, c, aSet: PNode): TImplication = if c.kind in {nkCharLit..nkUInt64Lit}: # fact: x <= 4; question x in {56}? # --> true if every value <= 4 is in the set {56} - # + # var value = newIntNode(c.kind, firstOrd(x.typ)) # don't iterate too often: if c.intVal - value.intVal < 1000: @@ -449,7 +463,7 @@ proc geImpliesIn(x, c, aSet: PNode): TImplication = if c.kind in {nkCharLit..nkUInt64Lit}: # fact: x >= 4; question x in {56}? # --> true iff every value >= 4 is in the set {56} - # + # var value = newIntNode(c.kind, c.intVal) let max = lastOrd(x.typ) # don't iterate too often: @@ -568,19 +582,19 @@ proc impliesLe(fact, x, c: PNode): TImplication = # fact: x < 4; question x <= 2? --> we don't know elif sameTree(fact.sons[2], x): # fact: 3 < x; question: x <= 1 ? --> false iff 1 <= 3 - if isValue(fact.sons[1]) and isValue(c): + if isValue(fact.sons[1]) and isValue(c): if leValue(c, fact.sons[1]): result = impNo - + of someLe: if sameTree(fact.sons[1], x): if isValue(fact.sons[2]) and isValue(c): # fact: x <= 4; question x <= 56? --> true iff 4 <= 56 if leValue(fact.sons[2], c): result = impYes # fact: x <= 4; question x <= 2? --> we don't know - + elif sameTree(fact.sons[2], x): # fact: 3 <= x; question: x <= 2 ? --> false iff 2 < 3 - if isValue(fact.sons[1]) and isValue(c): + if isValue(fact.sons[1]) and isValue(c): if leValue(c, fact.sons[1].pred): result = impNo of mNot, mOr, mAnd: internalError(x.info, "impliesLe") @@ -614,7 +628,7 @@ proc factImplies(fact, prop: PNode): TImplication = # it's provably wrong if every value > 4 is in the set {56} # That's because we compute the implication and 'a -> not b' cannot # be treated the same as 'not a -> b' - + # (not a) -> b compute as not (a -> b) ??? # == not a or not b == not (a and b) let arg = fact.sons[1] @@ -635,7 +649,7 @@ proc factImplies(fact, prop: PNode): TImplication = if result != impUnknown: return result return factImplies(fact.sons[2], prop) else: discard - + case prop.sons[0].sym.magic of mNot: result = ~fact.factImplies(prop.sons[1]) of mIsNil: result = impliesIsNil(fact, prop) @@ -671,6 +685,7 @@ proc pleViaModel(model: TModel; aa, bb: PNode): TImplication proc ple(m: TModel; a, b: PNode): TImplication = template `<=?`(a,b): expr = ple(m,a,b) == impYes + # 0 <= 3 if a.isValue and b.isValue: return if leValue(a, b): impYes else: impNo @@ -744,16 +759,21 @@ proc pleViaModelRec(m: var TModel; a, b: PNode): TImplication = # mark as used: m[i] = nil if ple(m, a, x) == impYes: - if ple(m, y, b) == impYes: return impYes + if ple(m, y, b) == impYes: + return impYes #if pleViaModelRec(m, y, b): return impYes # fact: 16 <= i # x y # question: i <= 15? no! result = impliesLe(fact, a, b) - if result != impUnknown: return result - if sameTree(y, a): - result = ple(m, b, x) - if result != impUnknown: return result + if result != impUnknown: + return result + when false: + # given: x <= y; y==a; x <= a this means: a <= b if x <= b + if sameTree(y, a): + result = ple(m, b, x) + if result != impUnknown: + return result proc pleViaModel(model: TModel; aa, bb: PNode): TImplication = # compute replacements: diff --git a/compiler/renderer.nim b/compiler/renderer.nim index ccf3837ed..689bf23c8 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -9,20 +9,20 @@ # This module implements the renderer of the standard Nim representation. -import +import lexer, options, idents, strutils, ast, msgs, lists -type - TRenderFlag* = enum - renderNone, renderNoBody, renderNoComments, renderDocComments, +type + TRenderFlag* = enum + renderNone, renderNoBody, renderNoComments, renderDocComments, renderNoPragmas, renderIds, renderNoProcDefs TRenderFlags* = set[TRenderFlag] - TRenderTok*{.final.} = object + TRenderTok*{.final.} = object kind*: TTokType length*: int16 TRenderTokSeq* = seq[TRenderTok] - TSrcGen*{.final.} = object + TSrcGen*{.final.} = object indent*: int lineLen*: int pos*: int # current position for iteration over the buffer @@ -41,6 +41,8 @@ proc renderModule*(n: PNode, filename: string, renderFlags: TRenderFlags = {}) proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string proc initTokRender*(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) proc getNextTok*(r: var TSrcGen, kind: var TTokType, literal: var string) + +proc `$`*(n: PNode): string = n.renderTree # implementation # We render the source code in a two phases: The first # determines how long the subtree will likely be, the second @@ -65,13 +67,13 @@ proc renderDefinitionName*(s: PSym, noQuotes = false): string = else: result = '`' & x & '`' -const +const IndentWidth = 2 longIndentWid = 4 MaxLineLen = 80 LineCommentColumn = 30 -proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) = +proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) = g.comStack = @[] g.tokens = @[] g.indent = 0 @@ -83,67 +85,67 @@ proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) = g.pendingNL = -1 g.checkAnon = false -proc addTok(g: var TSrcGen, kind: TTokType, s: string) = +proc addTok(g: var TSrcGen, kind: TTokType, s: string) = var length = len(g.tokens) setLen(g.tokens, length + 1) g.tokens[length].kind = kind g.tokens[length].length = int16(len(s)) add(g.buf, s) -proc addPendingNL(g: var TSrcGen) = - if g.pendingNL >= 0: +proc addPendingNL(g: var TSrcGen) = + if g.pendingNL >= 0: addTok(g, tkSpaces, "\n" & spaces(g.pendingNL)) g.lineLen = g.pendingNL g.pendingNL = - 1 -proc putNL(g: var TSrcGen, indent: int) = +proc putNL(g: var TSrcGen, indent: int) = if g.pendingNL >= 0: addPendingNL(g) else: addTok(g, tkSpaces, "\n") g.pendingNL = indent g.lineLen = indent -proc putNL(g: var TSrcGen) = +proc putNL(g: var TSrcGen) = putNL(g, g.indent) -proc optNL(g: var TSrcGen, indent: int) = +proc optNL(g: var TSrcGen, indent: int) = g.pendingNL = indent g.lineLen = indent # BUGFIX - -proc optNL(g: var TSrcGen) = + +proc optNL(g: var TSrcGen) = optNL(g, g.indent) -proc indentNL(g: var TSrcGen) = +proc indentNL(g: var TSrcGen) = inc(g.indent, IndentWidth) g.pendingNL = g.indent g.lineLen = g.indent -proc dedent(g: var TSrcGen) = +proc dedent(g: var TSrcGen) = dec(g.indent, IndentWidth) assert(g.indent >= 0) - if g.pendingNL > IndentWidth: + if g.pendingNL > IndentWidth: dec(g.pendingNL, IndentWidth) dec(g.lineLen, IndentWidth) -proc put(g: var TSrcGen, kind: TTokType, s: string) = +proc put(g: var TSrcGen, kind: TTokType, s: string) = addPendingNL(g) - if len(s) > 0: + if len(s) > 0: addTok(g, kind, s) inc(g.lineLen, len(s)) -proc putLong(g: var TSrcGen, kind: TTokType, s: string, lineLen: int) = +proc putLong(g: var TSrcGen, kind: TTokType, s: string, lineLen: int) = # use this for tokens over multiple lines. addPendingNL(g) addTok(g, kind, s) g.lineLen = lineLen -proc toNimChar(c: char): string = +proc toNimChar(c: char): string = case c of '\0': result = "\\0" of '\x01'..'\x1F', '\x80'..'\xFF': result = "\\x" & strutils.toHex(ord(c), 2) of '\'', '\"', '\\': result = '\\' & c else: result = c & "" - -proc makeNimString(s: string): string = + +proc makeNimString(s: string): string = result = "\"" for i in countup(0, len(s)-1): add(result, toNimChar(s[i])) add(result, '\"') @@ -174,7 +176,7 @@ proc putComment(g: var TSrcGen, s: string) = add(com, s[i]) inc(i) comIndent = 0 - while s[i] == ' ': + while s[i] == ' ': add(com, s[i]) inc(i) inc(comIndent) @@ -187,109 +189,109 @@ proc putComment(g: var TSrcGen, s: string) = # compute length of the following word: var j = i while s[j] > ' ': inc(j) - if not isCode and (g.lineLen + (j - i) > MaxLineLen): + if not isCode and (g.lineLen + (j - i) > MaxLineLen): put(g, tkComment, com) optNL(g, ind) com = '#' & spaces(comIndent) - while s[i] > ' ': + while s[i] > ' ': add(com, s[i]) inc(i) put(g, tkComment, com) optNL(g) -proc maxLineLength(s: string): int = +proc maxLineLength(s: string): int = if s.isNil: return 0 var i = 0 var lineLen = 0 while true: case s[i] - of '\0': - break - of '\x0D': + of '\0': + break + of '\x0D': inc(i) if s[i] == '\x0A': inc(i) result = max(result, lineLen) lineLen = 0 - of '\x0A': + of '\x0A': inc(i) result = max(result, lineLen) lineLen = 0 - else: + else: inc(lineLen) inc(i) -proc putRawStr(g: var TSrcGen, kind: TTokType, s: string) = +proc putRawStr(g: var TSrcGen, kind: TTokType, s: string) = var i = 0 var hi = len(s) - 1 var str = "" - while i <= hi: + while i <= hi: case s[i] - of '\x0D': + of '\x0D': put(g, kind, str) str = "" inc(i) if (i <= hi) and (s[i] == '\x0A'): inc(i) optNL(g, 0) - of '\x0A': + of '\x0A': put(g, kind, str) str = "" inc(i) optNL(g, 0) - else: + else: add(str, s[i]) inc(i) put(g, kind, str) -proc containsNL(s: string): bool = - for i in countup(0, len(s) - 1): +proc containsNL(s: string): bool = + for i in countup(0, len(s) - 1): case s[i] - of '\x0D', '\x0A': + of '\x0D', '\x0A': return true - else: + else: discard result = false -proc pushCom(g: var TSrcGen, n: PNode) = +proc pushCom(g: var TSrcGen, n: PNode) = var length = len(g.comStack) setLen(g.comStack, length + 1) g.comStack[length] = n -proc popAllComs(g: var TSrcGen) = +proc popAllComs(g: var TSrcGen) = setLen(g.comStack, 0) -proc popCom(g: var TSrcGen) = +proc popCom(g: var TSrcGen) = setLen(g.comStack, len(g.comStack) - 1) -const +const Space = " " -proc shouldRenderComment(g: var TSrcGen, n: PNode): bool = +proc shouldRenderComment(g: var TSrcGen, n: PNode): bool = result = false - if n.comment != nil: + if n.comment != nil: result = (renderNoComments notin g.flags) or (renderDocComments in g.flags) and startsWith(n.comment, "##") - -proc gcom(g: var TSrcGen, n: PNode) = + +proc gcom(g: var TSrcGen, n: PNode) = assert(n != nil) - if shouldRenderComment(g, n): + if shouldRenderComment(g, n): if (g.pendingNL < 0) and (len(g.buf) > 0) and (g.buf[len(g.buf)-1] != ' '): - put(g, tkSpaces, Space) + put(g, tkSpaces, Space) # Before long comments we cannot make sure that a newline is generated, # because this might be wrong. But it is no problem in practice. if (g.pendingNL < 0) and (len(g.buf) > 0) and - (g.lineLen < LineCommentColumn): + (g.lineLen < LineCommentColumn): var ml = maxLineLength(n.comment) - if ml + LineCommentColumn <= MaxLineLen: + if ml + LineCommentColumn <= MaxLineLen: put(g, tkSpaces, spaces(LineCommentColumn - g.lineLen)) putComment(g, n.comment) #assert(g.comStack[high(g.comStack)] = n); - -proc gcoms(g: var TSrcGen) = + +proc gcoms(g: var TSrcGen) = for i in countup(0, high(g.comStack)): gcom(g, g.comStack[i]) popAllComs(g) proc lsub(n: PNode): int proc litAux(n: PNode, x: BiggestInt, size: int): string = - proc skip(t: PType): PType = + proc skip(t: PType): PType = result = t while result.kind in {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal, tyConst, tyMutable}: @@ -299,20 +301,20 @@ proc litAux(n: PNode, x: BiggestInt, size: int): string = # we need a slow linear search because of enums with holes: for e in items(enumfields): if e.sym.position == x: return e.sym.name.s - + if nfBase2 in n.flags: result = "0b" & toBin(x, size * 8) elif nfBase8 in n.flags: result = "0o" & toOct(x, size * 3) elif nfBase16 in n.flags: result = "0x" & toHex(x, size * 2) else: result = $x -proc ulitAux(n: PNode, x: BiggestInt, size: int): string = +proc ulitAux(n: PNode, x: BiggestInt, size: int): string = if nfBase2 in n.flags: result = "0b" & toBin(x, size * 8) elif nfBase8 in n.flags: result = "0o" & toOct(x, size * 3) elif nfBase16 in n.flags: result = "0x" & toHex(x, size * 2) else: result = $x # XXX proper unsigned output! - -proc atom(n: PNode): string = + +proc atom(n: PNode): string = var f: float32 case n.kind of nkEmpty: result = "" @@ -335,49 +337,49 @@ proc atom(n: PNode): string = of nkFloatLit: if n.flags * {nfBase2, nfBase8, nfBase16} == {}: result = $(n.floatVal) else: result = litAux(n, (cast[PInt64](addr(n.floatVal)))[] , 8) - of nkFloat32Lit: - if n.flags * {nfBase2, nfBase8, nfBase16} == {}: + of nkFloat32Lit: + if n.flags * {nfBase2, nfBase8, nfBase16} == {}: result = $n.floatVal & "\'f32" - else: + else: f = n.floatVal.float32 result = litAux(n, (cast[PInt32](addr(f)))[], 4) & "\'f32" - of nkFloat64Lit: - if n.flags * {nfBase2, nfBase8, nfBase16} == {}: + of nkFloat64Lit: + if n.flags * {nfBase2, nfBase8, nfBase16} == {}: result = $n.floatVal & "\'f64" - else: + else: result = litAux(n, (cast[PInt64](addr(n.floatVal)))[], 8) & "\'f64" of nkNilLit: result = "nil" - of nkType: + of nkType: if (n.typ != nil) and (n.typ.sym != nil): result = n.typ.sym.name.s else: result = "[type node]" - else: + else: internalError("rnimsyn.atom " & $n.kind) result = "" - -proc lcomma(n: PNode, start: int = 0, theEnd: int = - 1): int = + +proc lcomma(n: PNode, start: int = 0, theEnd: int = - 1): int = assert(theEnd < 0) result = 0 - for i in countup(start, sonsLen(n) + theEnd): + for i in countup(start, sonsLen(n) + theEnd): inc(result, lsub(n.sons[i])) inc(result, 2) # for ``, `` - if result > 0: + if result > 0: dec(result, 2) # last does not get a comma! - -proc lsons(n: PNode, start: int = 0, theEnd: int = - 1): int = + +proc lsons(n: PNode, start: int = 0, theEnd: int = - 1): int = assert(theEnd < 0) result = 0 for i in countup(start, sonsLen(n) + theEnd): inc(result, lsub(n.sons[i])) - -proc lsub(n: PNode): int = + +proc lsub(n: PNode): int = # computes the length of a tree if isNil(n): return 0 if n.comment != nil: return MaxLineLen + 1 case n.kind of nkEmpty: result = 0 - of nkTripleStrLit: + of nkTripleStrLit: if containsNL(n.strVal): result = MaxLineLen + 1 else: result = len(atom(n)) - of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit: + of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit: result = len(atom(n)) of nkCall, nkBracketExpr, nkCurlyExpr, nkConv, nkPattern, nkObjConstr: result = lsub(n.sons[0]) + lcomma(n, 1) + 2 @@ -392,7 +394,7 @@ proc lsub(n: PNode): int = of nkArgList: result = lcomma(n) of nkTableConstr: result = if n.len > 0: lcomma(n) + 2 else: len("{:}") - of nkClosedSymChoice, nkOpenSymChoice: + of nkClosedSymChoice, nkOpenSymChoice: result = lsons(n) + len("()") + sonsLen(n) - 1 of nkTupleTy: result = lcomma(n) + len("tuple[]") of nkTupleClassTy: result = len("tuple") @@ -403,7 +405,7 @@ proc lsub(n: PNode): int = of nkCheckedFieldExpr: result = lsub(n.sons[0]) of nkLambda: result = lsons(n) + len("proc__=_") of nkDo: result = lsons(n) + len("do__:_") - of nkConstDef, nkIdentDefs: + of nkConstDef, nkIdentDefs: result = lcomma(n, 0, - 3) var L = sonsLen(n) if n.sons[L - 2].kind != nkEmpty: result = result + lsub(n.sons[L - 2]) + 2 @@ -412,7 +414,7 @@ proc lsub(n: PNode): int = of nkChckRangeF: result = len("chckRangeF") + 2 + lcomma(n) of nkChckRange64: result = len("chckRange64") + 2 + lcomma(n) of nkChckRange: result = len("chckRange") + 2 + lcomma(n) - of nkObjDownConv, nkObjUpConv, nkStringToCString, nkCStringToString: + of nkObjDownConv, nkObjUpConv, nkStringToCString, nkCStringToString: result = 2 if sonsLen(n) >= 1: result = result + lsub(n.sons[0]) result = result + lcomma(n, 1) @@ -426,7 +428,7 @@ proc lsub(n: PNode): int = of nkRange: result = lsons(n) + 2 of nkDerefExpr: result = lsub(n.sons[0]) + 2 of nkAccQuoted: result = lsons(n) + 2 - of nkIfExpr: + of nkIfExpr: result = lsub(n.sons[0].sons[0]) + lsub(n.sons[0].sons[1]) + lsons(n, 1) + len("if_:_") of nkElifExpr: result = lsons(n) + len("_elif_:_") @@ -447,13 +449,13 @@ proc lsub(n: PNode): int = of nkProcTy: result = lsons(n) + len("proc_") of nkIteratorTy: result = lsons(n) + len("iterator_") of nkSharedTy: result = lsons(n) + len("shared_") - of nkEnumTy: + of nkEnumTy: if sonsLen(n) > 0: result = lsub(n.sons[0]) + lcomma(n, 1) + len("enum_") else: result = len("enum") of nkEnumFieldDef: result = lsons(n) + 3 - of nkVarSection, nkLetSection: + of nkVarSection, nkLetSection: if sonsLen(n) > 1: result = MaxLineLen + 1 else: result = lsons(n) + len("var_") of nkReturnStmt: result = lsub(n.sons[0]) + len("return_") @@ -470,50 +472,50 @@ proc lsub(n: PNode): int = of nkElse: result = lsub(n.sons[0]) + len("else:_") of nkFinally: result = lsub(n.sons[0]) + len("finally:_") of nkGenericParams: result = lcomma(n) + 2 - of nkFormalParams: + of nkFormalParams: result = lcomma(n, 1) + 2 if n.sons[0].kind != nkEmpty: result = result + lsub(n.sons[0]) + 2 - of nkExceptBranch: + of nkExceptBranch: result = lcomma(n, 0, -2) + lsub(lastSon(n)) + len("except_:_") else: result = MaxLineLen + 1 - -proc fits(g: TSrcGen, x: int): bool = + +proc fits(g: TSrcGen, x: int): bool = result = x + g.lineLen <= MaxLineLen -type - TSubFlag = enum +type + TSubFlag = enum rfLongMode, rfNoIndent, rfInConstExpr TSubFlags = set[TSubFlag] TContext = tuple[spacing: int, flags: TSubFlags] -const +const emptyContext: TContext = (spacing: 0, flags: {}) -proc initContext(c: var TContext) = +proc initContext(c: var TContext) = c.spacing = 0 c.flags = {} proc gsub(g: var TSrcGen, n: PNode, c: TContext) -proc gsub(g: var TSrcGen, n: PNode) = +proc gsub(g: var TSrcGen, n: PNode) = var c: TContext initContext(c) gsub(g, n, c) -proc hasCom(n: PNode): bool = +proc hasCom(n: PNode): bool = result = false if n.comment != nil: return true case n.kind of nkEmpty..nkNilLit: discard - else: - for i in countup(0, sonsLen(n) - 1): + else: + for i in countup(0, sonsLen(n) - 1): if hasCom(n.sons[i]): return true - -proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) = + +proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) = put(g, kind, s) put(g, tkSpaces, Space) -proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0, - theEnd: int = - 1, separator = tkComma) = +proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0, + theEnd: int = - 1, separator = tkComma) = for i in countup(start, sonsLen(n) + theEnd): var c = i < sonsLen(n) + theEnd var sublen = lsub(n.sons[i]) + ord(c) @@ -523,54 +525,54 @@ proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0, if c: if g.tokens.len > oldLen: putWithSpace(g, separator, TokTypeToStr[separator]) - if hasCom(n.sons[i]): + if hasCom(n.sons[i]): gcoms(g) optNL(g, ind) -proc gcomma(g: var TSrcGen, n: PNode, c: TContext, start: int = 0, - theEnd: int = - 1) = +proc gcomma(g: var TSrcGen, n: PNode, c: TContext, start: int = 0, + theEnd: int = - 1) = var ind: int - if rfInConstExpr in c.flags: + if rfInConstExpr in c.flags: ind = g.indent + IndentWidth - else: + else: ind = g.lineLen if ind > MaxLineLen div 2: ind = g.indent + longIndentWid gcommaAux(g, n, ind, start, theEnd) -proc gcomma(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) = +proc gcomma(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) = var ind = g.lineLen if ind > MaxLineLen div 2: ind = g.indent + longIndentWid gcommaAux(g, n, ind, start, theEnd) -proc gsemicolon(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) = +proc gsemicolon(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) = var ind = g.lineLen if ind > MaxLineLen div 2: ind = g.indent + longIndentWid gcommaAux(g, n, ind, start, theEnd, tkSemiColon) -proc gsons(g: var TSrcGen, n: PNode, c: TContext, start: int = 0, - theEnd: int = - 1) = +proc gsons(g: var TSrcGen, n: PNode, c: TContext, start: int = 0, + theEnd: int = - 1) = for i in countup(start, sonsLen(n) + theEnd): gsub(g, n.sons[i], c) -proc gsection(g: var TSrcGen, n: PNode, c: TContext, kind: TTokType, - k: string) = +proc gsection(g: var TSrcGen, n: PNode, c: TContext, kind: TTokType, + k: string) = if sonsLen(n) == 0: return # empty var sections are possible putWithSpace(g, kind, k) gcoms(g) indentNL(g) - for i in countup(0, sonsLen(n) - 1): + for i in countup(0, sonsLen(n) - 1): optNL(g) gsub(g, n.sons[i], c) gcoms(g) dedent(g) -proc longMode(n: PNode, start: int = 0, theEnd: int = - 1): bool = +proc longMode(n: PNode, start: int = 0, theEnd: int = - 1): bool = result = n.comment != nil - if not result: + if not result: # check further - for i in countup(start, sonsLen(n) + theEnd): - if (lsub(n.sons[i]) > MaxLineLen): + for i in countup(start, sonsLen(n) + theEnd): + if (lsub(n.sons[i]) > MaxLineLen): result = true - break + break proc gstmts(g: var TSrcGen, n: PNode, c: TContext, doIndent=true) = if n.kind == nkEmpty: return @@ -590,33 +592,33 @@ proc gstmts(g: var TSrcGen, n: PNode, c: TContext, doIndent=true) = gcoms(g) optNL(g) if rfLongMode in c.flags: dedent(g) - -proc gif(g: var TSrcGen, n: PNode) = + +proc gif(g: var TSrcGen, n: PNode) = var c: TContext gsub(g, n.sons[0].sons[0]) initContext(c) putWithSpace(g, tkColon, ":") - if longMode(n) or (lsub(n.sons[0].sons[1]) + g.lineLen > MaxLineLen): + if longMode(n) or (lsub(n.sons[0].sons[1]) + g.lineLen > MaxLineLen): incl(c.flags, rfLongMode) gcoms(g) # a good place for comments gstmts(g, n.sons[0].sons[1], c) var length = sonsLen(n) - for i in countup(1, length - 1): + for i in countup(1, length - 1): optNL(g) gsub(g, n.sons[i], c) -proc gwhile(g: var TSrcGen, n: PNode) = +proc gwhile(g: var TSrcGen, n: PNode) = var c: TContext putWithSpace(g, tkWhile, "while") gsub(g, n.sons[0]) putWithSpace(g, tkColon, ":") initContext(c) - if longMode(n) or (lsub(n.sons[1]) + g.lineLen > MaxLineLen): + if longMode(n) or (lsub(n.sons[1]) + g.lineLen > MaxLineLen): incl(c.flags, rfLongMode) gcoms(g) # a good place for comments gstmts(g, n.sons[1], c) -proc gpattern(g: var TSrcGen, n: PNode) = +proc gpattern(g: var TSrcGen, n: PNode) = var c: TContext put(g, tkCurlyLe, "{") initContext(c) @@ -626,7 +628,7 @@ proc gpattern(g: var TSrcGen, n: PNode) = gstmts(g, n, c) put(g, tkCurlyRi, "}") -proc gpragmaBlock(g: var TSrcGen, n: PNode) = +proc gpragmaBlock(g: var TSrcGen, n: PNode) = var c: TContext gsub(g, n.sons[0]) putWithSpace(g, tkColon, ":") @@ -636,25 +638,25 @@ proc gpragmaBlock(g: var TSrcGen, n: PNode) = gcoms(g) # a good place for comments gstmts(g, n.sons[1], c) -proc gtry(g: var TSrcGen, n: PNode) = +proc gtry(g: var TSrcGen, n: PNode) = var c: TContext put(g, tkTry, "try") putWithSpace(g, tkColon, ":") initContext(c) - if longMode(n) or (lsub(n.sons[0]) + g.lineLen > MaxLineLen): + if longMode(n) or (lsub(n.sons[0]) + g.lineLen > MaxLineLen): incl(c.flags, rfLongMode) gcoms(g) # a good place for comments gstmts(g, n.sons[0], c) gsons(g, n, c, 1) -proc gfor(g: var TSrcGen, n: PNode) = +proc gfor(g: var TSrcGen, n: PNode) = var c: TContext var length = sonsLen(n) putWithSpace(g, tkFor, "for") initContext(c) if longMode(n) or (lsub(n.sons[length - 1]) + lsub(n.sons[length - 2]) + 6 + g.lineLen > - MaxLineLen): + MaxLineLen): incl(c.flags, rfLongMode) gcomma(g, n, c, 0, - 3) put(g, tkSpaces, Space) @@ -664,17 +666,17 @@ proc gfor(g: var TSrcGen, n: PNode) = gcoms(g) gstmts(g, n.sons[length - 1], c) -proc gmacro(g: var TSrcGen, n: PNode) = +proc gmacro(g: var TSrcGen, n: PNode) = var c: TContext initContext(c) gsub(g, n.sons[0]) putWithSpace(g, tkColon, ":") - if longMode(n) or (lsub(n.sons[1]) + g.lineLen > MaxLineLen): + if longMode(n) or (lsub(n.sons[1]) + g.lineLen > MaxLineLen): incl(c.flags, rfLongMode) gcoms(g) gsons(g, n, c, 1) -proc gcase(g: var TSrcGen, n: PNode) = +proc gcase(g: var TSrcGen, n: PNode) = var c: TContext initContext(c) var length = sonsLen(n) @@ -685,18 +687,18 @@ proc gcase(g: var TSrcGen, n: PNode) = gcoms(g) optNL(g) gsons(g, n, c, 1, last) - if last == - 2: + if last == - 2: initContext(c) if longMode(n.sons[length - 1]): incl(c.flags, rfLongMode) gsub(g, n.sons[length - 1], c) -proc gproc(g: var TSrcGen, n: PNode) = +proc gproc(g: var TSrcGen, n: PNode) = var c: TContext if n.sons[namePos].kind == nkSym: put(g, tkSymbol, renderDefinitionName(n.sons[namePos].sym)) else: gsub(g, n.sons[namePos]) - + if n.sons[patternPos].kind != nkEmpty: gpattern(g, n.sons[patternPos]) let oldCheckAnon = g.checkAnon @@ -733,7 +735,7 @@ proc gTypeClassTy(g: var TSrcGen, n: PNode) = gstmts(g, n[3], c) dedent(g) -proc gblock(g: var TSrcGen, n: PNode) = +proc gblock(g: var TSrcGen, n: PNode) = var c: TContext initContext(c) if n.sons[0].kind != nkEmpty: @@ -742,7 +744,7 @@ proc gblock(g: var TSrcGen, n: PNode) = else: put(g, tkBlock, "block") putWithSpace(g, tkColon, ":") - if longMode(n) or (lsub(n.sons[1]) + g.lineLen > MaxLineLen): + if longMode(n) or (lsub(n.sons[1]) + g.lineLen > MaxLineLen): incl(c.flags, rfLongMode) gcoms(g) # XXX I don't get why this is needed here! gstmts should already handle this! @@ -750,17 +752,17 @@ proc gblock(g: var TSrcGen, n: PNode) = gstmts(g, n.sons[1], c) dedent(g) -proc gstaticStmt(g: var TSrcGen, n: PNode) = +proc gstaticStmt(g: var TSrcGen, n: PNode) = var c: TContext putWithSpace(g, tkStatic, "static") putWithSpace(g, tkColon, ":") initContext(c) - if longMode(n) or (lsub(n.sons[0]) + g.lineLen > MaxLineLen): + if longMode(n) or (lsub(n.sons[0]) + g.lineLen > MaxLineLen): incl(c.flags, rfLongMode) gcoms(g) # a good place for comments gstmts(g, n.sons[0], c) -proc gasm(g: var TSrcGen, n: PNode) = +proc gasm(g: var TSrcGen, n: PNode) = putWithSpace(g, tkAsm, "asm") gsub(g, n.sons[0]) gcoms(g) @@ -770,16 +772,16 @@ proc gident(g: var TSrcGen, n: PNode) = if g.checkAnon and n.kind == nkSym and sfAnon in n.sym.flags: return var t: TTokType var s = atom(n) - if (s[0] in lexer.SymChars): - if (n.kind == nkIdent): + if (s[0] in lexer.SymChars): + if (n.kind == nkIdent): if (n.ident.id < ord(tokKeywordLow) - ord(tkSymbol)) or - (n.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)): + (n.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)): t = tkSymbol - else: + else: t = TTokType(n.ident.id + ord(tkSymbol)) - else: + else: t = tkSymbol - else: + else: t = tkOpr put(g, t, s) if n.kind == nkSym and renderIds in g.flags: put(g, tkIntLit, $n.sym.id) @@ -789,12 +791,12 @@ proc doParamsAux(g: var TSrcGen, params: PNode) = put(g, tkParLe, "(") gsemicolon(g, params, 1) put(g, tkParRi, ")") - - if params.sons[0].kind != nkEmpty: + + if params.sons[0].kind != nkEmpty: putWithSpace(g, tkOpr, "->") gsub(g, params.sons[0]) -proc gsub(g: var TSrcGen, n: PNode, c: TContext) = +proc gsub(g: var TSrcGen, n: PNode, c: TContext) = if isNil(n): return var a: TContext @@ -827,14 +829,14 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = put(g, tkParLe, "(") gcomma(g, n, 1) put(g, tkParRi, ")") - of nkCallStrLit: + of nkCallStrLit: gsub(g, n.sons[0]) - if n.sons[1].kind == nkRStrLit: + if n.sons[1].kind == nkRStrLit: put(g, tkRStrLit, '\"' & replace(n[1].strVal, "\"", "\"\"") & '\"') - else: + else: gsub(g, n.sons[1]) of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: gsub(g, n.sons[1]) - of nkCast: + of nkCast: put(g, tkCast, "cast") put(g, tkBracketLe, "[") gsub(g, n.sons[0]) @@ -842,7 +844,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = put(g, tkParLe, "(") gsub(g, n.sons[1]) put(g, tkParRi, ")") - of nkAddr: + of nkAddr: put(g, tkAddr, "addr") put(g, tkParLe, "(") gsub(g, n.sons[0]) @@ -851,7 +853,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = put(g, tkStatic, "static") put(g, tkSpaces, Space) gsub(g, n.sons[0]) - of nkBracketExpr: + of nkBracketExpr: gsub(g, n.sons[0]) put(g, tkBracketLe, "[") gcomma(g, n, 1) @@ -861,41 +863,41 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = put(g, tkCurlyLe, "{") gcomma(g, n, 1) put(g, tkCurlyRi, "}") - of nkPragmaExpr: + of nkPragmaExpr: gsub(g, n.sons[0]) gcomma(g, n, 1) - of nkCommand: + of nkCommand: gsub(g, n.sons[0]) put(g, tkSpaces, Space) gcomma(g, n, 1) - of nkExprEqExpr, nkAsgn, nkFastAsgn: + of nkExprEqExpr, nkAsgn, nkFastAsgn: gsub(g, n.sons[0]) put(g, tkSpaces, Space) putWithSpace(g, tkEquals, "=") gsub(g, n.sons[1]) - of nkChckRangeF: + of nkChckRangeF: put(g, tkSymbol, "chckRangeF") put(g, tkParLe, "(") gcomma(g, n) put(g, tkParRi, ")") - of nkChckRange64: + of nkChckRange64: put(g, tkSymbol, "chckRange64") put(g, tkParLe, "(") gcomma(g, n) put(g, tkParRi, ")") - of nkChckRange: + of nkChckRange: put(g, tkSymbol, "chckRange") put(g, tkParLe, "(") gcomma(g, n) put(g, tkParRi, ")") - of nkObjDownConv, nkObjUpConv, nkStringToCString, nkCStringToString: + of nkObjDownConv, nkObjUpConv, nkStringToCString, nkCStringToString: if sonsLen(n) >= 1: gsub(g, n.sons[0]) put(g, tkParLe, "(") gcomma(g, n, 1) put(g, tkParRi, ")") of nkClosedSymChoice, nkOpenSymChoice: put(g, tkParLe, "(") - for i in countup(0, sonsLen(n) - 1): + for i in countup(0, sonsLen(n) - 1): if i > 0: put(g, tkOpr, "|") if n.sons[i].kind == nkSym: let s = n[i].sym @@ -906,11 +908,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = else: gsub(g, n.sons[i], c) put(g, tkParRi, if n.kind == nkOpenSymChoice: "|...)" else: ")") - of nkPar, nkClosure: + of nkPar, nkClosure: put(g, tkParLe, "(") gcomma(g, n, c) put(g, tkParRi, ")") - of nkCurly: + of nkCurly: put(g, tkCurlyLe, "{") gcomma(g, n, c) put(g, tkCurlyRi, "}") @@ -925,14 +927,14 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = put(g, tkBracketLe, "[") gcomma(g, n, c) put(g, tkBracketRi, "]") - of nkDotExpr: + of nkDotExpr: gsub(g, n.sons[0]) put(g, tkDot, ".") gsub(g, n.sons[1]) - of nkBind: + of nkBind: putWithSpace(g, tkBind, "bind") gsub(g, n.sons[0]) - of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref: + of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref: gsub(g, n.sons[0]) of nkLambda: putWithSpace(g, tkProc, "proc") @@ -950,34 +952,34 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = of nkConstDef, nkIdentDefs: gcomma(g, n, 0, -3) var L = sonsLen(n) - if L >= 2 and n.sons[L - 2].kind != nkEmpty: + if L >= 2 and n.sons[L - 2].kind != nkEmpty: putWithSpace(g, tkColon, ":") gsub(g, n.sons[L - 2]) - if L >= 1 and n.sons[L - 1].kind != nkEmpty: + if L >= 1 and n.sons[L - 1].kind != nkEmpty: put(g, tkSpaces, Space) putWithSpace(g, tkEquals, "=") gsub(g, n.sons[L - 1], c) - of nkVarTuple: + of nkVarTuple: put(g, tkParLe, "(") gcomma(g, n, 0, -3) put(g, tkParRi, ")") put(g, tkSpaces, Space) putWithSpace(g, tkEquals, "=") gsub(g, lastSon(n), c) - of nkExprColonExpr: + of nkExprColonExpr: gsub(g, n.sons[0]) putWithSpace(g, tkColon, ":") gsub(g, n.sons[1]) - of nkInfix: + of nkInfix: gsub(g, n.sons[1]) put(g, tkSpaces, Space) gsub(g, n.sons[0]) # binary operator - if not fits(g, lsub(n.sons[2]) + lsub(n.sons[0]) + 1): + if not fits(g, lsub(n.sons[2]) + lsub(n.sons[0]) + 1): optNL(g, g.indent + longIndentWid) - else: + else: put(g, tkSpaces, Space) gsub(g, n.sons[2]) - of nkPrefix: + of nkPrefix: gsub(g, n.sons[0]) if n.len > 1: put(g, tkSpaces, Space) @@ -987,10 +989,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = put(g, tkParRi, ")") else: gsub(g, n.sons[1]) - of nkPostfix: + of nkPostfix: gsub(g, n.sons[1]) gsub(g, n.sons[0]) - of nkRange: + of nkRange: gsub(g, n.sons[0]) put(g, tkDotDot, "..") gsub(g, n.sons[1]) @@ -1004,43 +1006,43 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = put(g, tkSpaces, Space) gsub(g, n.sons[i]) put(g, tkAccent, "`") - of nkIfExpr: + of nkIfExpr: putWithSpace(g, tkIf, "if") gsub(g, n.sons[0].sons[0]) putWithSpace(g, tkColon, ":") gsub(g, n.sons[0].sons[1]) gsons(g, n, emptyContext, 1) - of nkElifExpr: + of nkElifExpr: putWithSpace(g, tkElif, " elif") gsub(g, n.sons[0]) putWithSpace(g, tkColon, ":") gsub(g, n.sons[1]) - of nkElseExpr: + of nkElseExpr: put(g, tkElse, " else") putWithSpace(g, tkColon, ":") gsub(g, n.sons[0]) of nkTypeOfExpr: putWithSpace(g, tkType, "type") if n.len > 0: gsub(g, n.sons[0]) - of nkRefTy: + of nkRefTy: if sonsLen(n) > 0: putWithSpace(g, tkRef, "ref") gsub(g, n.sons[0]) else: put(g, tkRef, "ref") - of nkPtrTy: + of nkPtrTy: if sonsLen(n) > 0: putWithSpace(g, tkPtr, "ptr") gsub(g, n.sons[0]) else: put(g, tkPtr, "ptr") - of nkVarTy: + of nkVarTy: if sonsLen(n) > 0: putWithSpace(g, tkVar, "var") gsub(g, n.sons[0]) else: put(g, tkVar, "var") - of nkDistinctTy: + of nkDistinctTy: if n.len > 0: putWithSpace(g, tkDistinct, "distinct") gsub(g, n.sons[0]) @@ -1052,14 +1054,14 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = gcomma(g, n[1]) else: put(g, tkDistinct, "distinct") - of nkTypeDef: + of nkTypeDef: gsub(g, n.sons[0]) gsub(g, n.sons[1]) put(g, tkSpaces, Space) - if n.sons[2].kind != nkEmpty: + if n.sons[2].kind != nkEmpty: putWithSpace(g, tkEquals, "=") gsub(g, n.sons[2]) - of nkObjectTy: + of nkObjectTy: if sonsLen(n) > 0: putWithSpace(g, tkObject, "object") gsub(g, n.sons[0]) @@ -1068,18 +1070,18 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = gsub(g, n.sons[2]) else: put(g, tkObject, "object") - of nkRecList: + of nkRecList: indentNL(g) - for i in countup(0, sonsLen(n) - 1): + for i in countup(0, sonsLen(n) - 1): optNL(g) gsub(g, n.sons[i], c) gcoms(g) dedent(g) putNL(g) - of nkOfInherit: + of nkOfInherit: putWithSpace(g, tkOf, "of") gsub(g, n.sons[0]) - of nkProcTy: + of nkProcTy: if sonsLen(n) > 0: putWithSpace(g, tkProc, "proc") gsub(g, n.sons[0]) @@ -1098,7 +1100,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = put(g, tkBracketLe, "[") if n.len > 0: gsub(g, n.sons[0]) - put(g, tkBracketRi, "]") + put(g, tkBracketRi, "]") of nkEnumTy: if sonsLen(n) > 0: putWithSpace(g, tkEnum, "enum") @@ -1110,16 +1112,16 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = dedent(g) else: put(g, tkEnum, "enum") - of nkEnumFieldDef: + of nkEnumFieldDef: gsub(g, n.sons[0]) put(g, tkSpaces, Space) putWithSpace(g, tkEquals, "=") gsub(g, n.sons[1]) of nkStmtList, nkStmtListExpr, nkStmtListType: gstmts(g, n, emptyContext) - of nkIfStmt: + of nkIfStmt: putWithSpace(g, tkIf, "if") gif(g, n) - of nkWhen, nkRecWhen: + of nkWhen, nkRecWhen: putWithSpace(g, tkWhen, "when") gif(g, n) of nkWhileStmt: gwhile(g, n) @@ -1130,27 +1132,27 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = of nkBlockStmt, nkBlockExpr: gblock(g, n) of nkStaticStmt: gstaticStmt(g, n) of nkAsmStmt: gasm(g, n) - of nkProcDef: + of nkProcDef: if renderNoProcDefs notin g.flags: putWithSpace(g, tkProc, "proc") gproc(g, n) of nkConverterDef: if renderNoProcDefs notin g.flags: putWithSpace(g, tkConverter, "converter") gproc(g, n) - of nkMethodDef: + of nkMethodDef: if renderNoProcDefs notin g.flags: putWithSpace(g, tkMethod, "method") gproc(g, n) - of nkIteratorDef: + of nkIteratorDef: if renderNoProcDefs notin g.flags: putWithSpace(g, tkIterator, "iterator") gproc(g, n) - of nkMacroDef: + of nkMacroDef: if renderNoProcDefs notin g.flags: putWithSpace(g, tkMacro, "macro") gproc(g, n) - of nkTemplateDef: + of nkTemplateDef: if renderNoProcDefs notin g.flags: putWithSpace(g, tkTemplate, "template") gproc(g, n) - of nkTypeSection: + of nkTypeSection: gsection(g, n, emptyContext, tkType, "type") - of nkConstSection: + of nkConstSection: initContext(a) incl(a.flags, rfInConstExpr) gsection(g, n, a, tkConst, "const") @@ -1159,32 +1161,32 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = if L == 0: return if n.kind == nkVarSection: putWithSpace(g, tkVar, "var") else: putWithSpace(g, tkLet, "let") - if L > 1: + if L > 1: gcoms(g) indentNL(g) - for i in countup(0, L - 1): + for i in countup(0, L - 1): optNL(g) gsub(g, n.sons[i]) gcoms(g) dedent(g) - else: + else: gsub(g, n.sons[0]) - of nkReturnStmt: + of nkReturnStmt: putWithSpace(g, tkReturn, "return") gsub(g, n.sons[0]) - of nkRaiseStmt: + of nkRaiseStmt: putWithSpace(g, tkRaise, "raise") gsub(g, n.sons[0]) - of nkYieldStmt: + of nkYieldStmt: putWithSpace(g, tkYield, "yield") gsub(g, n.sons[0]) - of nkDiscardStmt: + of nkDiscardStmt: putWithSpace(g, tkDiscard, "discard") gsub(g, n.sons[0]) - of nkBreakStmt: + of nkBreakStmt: putWithSpace(g, tkBreak, "break") gsub(g, n.sons[0]) - of nkContinueStmt: + of nkContinueStmt: putWithSpace(g, tkContinue, "continue") gsub(g, n.sons[0]) of nkPragma: @@ -1219,24 +1221,24 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = gcommaAux(g, n, g.indent, 1) gcoms(g) putNL(g) - of nkFromStmt: + of nkFromStmt: putWithSpace(g, tkFrom, "from") gsub(g, n.sons[0]) put(g, tkSpaces, Space) putWithSpace(g, tkImport, "import") gcomma(g, n, emptyContext, 1) putNL(g) - of nkIncludeStmt: + of nkIncludeStmt: putWithSpace(g, tkInclude, "include") gcoms(g) indentNL(g) gcommaAux(g, n, g.indent) dedent(g) putNL(g) - of nkCommentStmt: + of nkCommentStmt: gcoms(g) optNL(g) - of nkOfBranch: + of nkOfBranch: optNL(g) putWithSpace(g, tkOf, "of") gcomma(g, n, c, 0, - 2) @@ -1248,50 +1250,50 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = put(g, tkSpaces, Space) putWithSpace(g, tkAs, "as") gsub(g, n.sons[1]) - of nkBindStmt: + of nkBindStmt: putWithSpace(g, tkBind, "bind") gcomma(g, n, c) of nkMixinStmt: putWithSpace(g, tkMixin, "mixin") gcomma(g, n, c) - of nkElifBranch: + of nkElifBranch: optNL(g) putWithSpace(g, tkElif, "elif") gsub(g, n.sons[0]) putWithSpace(g, tkColon, ":") gcoms(g) gstmts(g, n.sons[1], c) - of nkElse: + of nkElse: optNL(g) put(g, tkElse, "else") putWithSpace(g, tkColon, ":") gcoms(g) gstmts(g, n.sons[0], c) - of nkFinally: + of nkFinally: optNL(g) put(g, tkFinally, "finally") putWithSpace(g, tkColon, ":") gcoms(g) gstmts(g, n.sons[0], c) - of nkExceptBranch: + of nkExceptBranch: optNL(g) putWithSpace(g, tkExcept, "except") gcomma(g, n, 0, - 2) putWithSpace(g, tkColon, ":") gcoms(g) gstmts(g, lastSon(n), c) - of nkGenericParams: + of nkGenericParams: put(g, tkBracketLe, "[") gcomma(g, n) put(g, tkBracketRi, "]") - of nkFormalParams: + of nkFormalParams: put(g, tkParLe, "(") gsemicolon(g, n, 1) put(g, tkParRi, ")") - if n.sons[0].kind != nkEmpty: + if n.sons[0].kind != nkEmpty: putWithSpace(g, tkColon, ":") gsub(g, n.sons[0]) - of nkTupleTy: + of nkTupleTy: put(g, tkTuple, "tuple") put(g, tkBracketLe, "[") gcomma(g, n) @@ -1309,17 +1311,17 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = gsons(g, n, c) of nkTypeClassTy: gTypeClassTy(g, n) - else: - #nkNone, nkExplicitTypeListCall: + else: + #nkNone, nkExplicitTypeListCall: internalError(n.info, "rnimsyn.gsub(" & $n.kind & ')') -proc renderTree(n: PNode, renderFlags: TRenderFlags = {}): string = +proc renderTree(n: PNode, renderFlags: TRenderFlags = {}): string = var g: TSrcGen initSrcGen(g, renderFlags) gsub(g, n) result = g.buf -proc renderModule(n: PNode, filename: string, +proc renderModule(n: PNode, filename: string, renderFlags: TRenderFlags = {}) = var f: File @@ -1339,18 +1341,18 @@ proc renderModule(n: PNode, filename: string, write(f, g.buf) close(f) else: - rawMessage(errCannotOpenFile, filename) + rawMessage(errCannotOpenFile, filename) -proc initTokRender(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) = +proc initTokRender(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) = initSrcGen(r, renderFlags) gsub(r, n) -proc getNextTok(r: var TSrcGen, kind: var TTokType, literal: var string) = - if r.idx < len(r.tokens): +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.int literal = substr(r.buf, r.pos, r.pos + length - 1) inc(r.pos, length) inc(r.idx) - else: + else: kind = tkEof diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim index a914832de..6572a7f49 100644 --- a/compiler/semparallel.nim +++ b/compiler/semparallel.nim @@ -37,7 +37,7 @@ is valid, but spawn f(a[i]) spawn f(a[i]) inc i -is not! However, +is not! However, spawn f(a[i]) if guard: inc i spawn f(a[i]) @@ -460,7 +460,7 @@ proc liftParallel*(owner: PSym; n: PNode): PNode = # - detect used slices # - detect used arguments #echo "PAR ", renderTree(n) - + var a = initAnalysisCtx() let body = n.lastSon analyse(a, body) diff --git a/compiler/transf.nim b/compiler/transf.nim index e5e3bbe63..7e56f09dc 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -152,6 +152,7 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode = defs[0] = newSymNode(newVar).PTransNode defs[1] = it.sons[1].PTransNode defs[2] = transform(c, it.sons[2]) + newVar.ast = defs[2].PNode result[i] = defs else: if it.kind != nkVarTuple: diff --git a/tests/parallel/tsimple_array_checks.nim b/tests/parallel/tsimple_array_checks.nim new file mode 100644 index 000000000..9874d3299 --- /dev/null +++ b/tests/parallel/tsimple_array_checks.nim @@ -0,0 +1,41 @@ +# bug #2287 + +import threadPool + +# If `nums` is an array instead of seq, +# NONE of the iteration ways below work (including high / len-1) +let nums = @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + +proc log(n:int) = + echo n + +proc main = + parallel: + for n in nums: # Error: cannot prove: i <= len(nums) + -1 + spawn log(n) + #for i in 0 .. <nums.len: # Error: cannot prove: i <= len(nums) + -1 + #for i in 0 .. nums.len-1: # WORKS! + #for i in 0 .. <nums.len: # WORKS! + # spawn log(nums[i]) + +# Array needs explicit size to work, probably related to issue #2287 +#const a: array[0..5, int] = [1,2,3,4,5,6] + +#const a = [1,2,3,4,5,6] # Doesn't work +const a = @[1,2,3,4,5,6] # Doesn't work +proc f(n: int) = echo "Hello ", n + +proc maino = + parallel: + # while loop doesn't work: + var i = 0 + while i < a.high: + #for i in countup(0, a.high-1, 2): + spawn f(a[i]) + spawn f(a[i+1]) + i += 2 + +maino() # Doesn't work outside a proc + +when isMainModule: + main() diff --git a/todo.txt b/todo.txt index 69674f019..47180aaf1 100644 --- a/todo.txt +++ b/todo.txt @@ -54,6 +54,7 @@ Bugs - VM: ptr/ref T cannot work in general - scopes are still broken for generic instantiation! - blocks can "export" an identifier but the CCG generates {} for them ... +- ConcreteTypes in a 'case' means we don't check for duplicated case branches version 0.9.x |