diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2018-01-27 07:59:40 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-01-27 07:59:40 +0100 |
commit | 68dfd1729e22835d9596b20d419a720ba6452781 (patch) | |
tree | 8d4729202e066b0f535aff618afd6f7002c0c77f | |
parent | 394757dbf521b8b4a16dd694a687039faeb21682 (diff) | |
download | Nim-68dfd1729e22835d9596b20d419a720ba6452781.tar.gz |
fixes #6989
-rw-r--r-- | compiler/semfold.nim | 7 | ||||
-rw-r--r-- | lib/system.nim | 12 | ||||
-rw-r--r-- | tests/array/troofregression2.nim | 104 |
3 files changed, 116 insertions, 7 deletions
diff --git a/compiler/semfold.nim b/compiler/semfold.nim index f690615ac..55cdc334c 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -30,7 +30,12 @@ proc newIntNodeT(intVal: BiggestInt, n: PNode): PNode = case skipTypes(n.typ, abstractVarRange).kind of tyInt: result = newIntNode(nkIntLit, intVal) - result.typ = getIntLitType(result) + # See bug #6989. 'pred' et al only produce an int literal type if the + # original type was 'int', not a distinct int etc. + if n.typ.kind == tyInt: + result.typ = getIntLitType(result) + else: + result.typ = n.typ # hrm, this is not correct: 1 + high(int) shouldn't produce tyInt64 ... #setIntLitType(result) of tyChar: diff --git a/lib/system.nim b/lib/system.nim index 2c0617e4d..4e071e802 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -318,7 +318,7 @@ type Slice*[T] = HSlice[T, T] ## an alias for ``HSlice[T, T]`` proc `..`*[T, U](a: T, b: U): HSlice[T, U] {.noSideEffect, inline, magic: "DotDot".} = - ## `slice`:idx: operator that constructs an interval ``[a, b]``, both `a` + ## binary `slice`:idx: operator that constructs an interval ``[a, b]``, both `a` ## and `b` are inclusive. Slices can also be used in the set constructor ## and in ordinal case statements, but then they are special-cased by the ## compiler. @@ -326,7 +326,7 @@ proc `..`*[T, U](a: T, b: U): HSlice[T, U] {.noSideEffect, inline, magic: "DotDo result.b = b proc `..`*[T](b: T): HSlice[int, T] {.noSideEffect, inline, magic: "DotDot".} = - ## `slice`:idx: operator that constructs an interval ``[default(int), b]`` + ## unary `slice`:idx: operator that constructs an interval ``[default(int), b]`` result.b = b when not defined(niminheritable): @@ -677,12 +677,12 @@ proc `<`*[T](x: Ordinal[T]): T {.magic: "UnaryLt", noSideEffect, deprecated.} ## write ``0 ..< 10`` instead of ``0 .. < 10`` (look at the spacing). ## For ``<x`` write ``pred(x)``. -proc succ*[T](x: Ordinal[T], y = 1): T {.magic: "Succ", noSideEffect.} +proc succ*[T: Ordinal](x: T, y = 1): T {.magic: "Succ", noSideEffect.} ## returns the ``y``-th successor of the value ``x``. ``T`` has to be ## an ordinal type. If such a value does not exist, ``EOutOfRange`` is raised ## or a compile time error occurs. -proc pred*[T](x: Ordinal[T], y = 1): T {.magic: "Pred", noSideEffect.} +proc pred*[T: Ordinal](x: T, y = 1): T {.magic: "Pred", noSideEffect.} ## returns the ``y``-th predecessor of the value ``x``. ``T`` has to be ## an ordinal type. If such a value does not exist, ``EOutOfRange`` is raised ## or a compile time error occurs. @@ -3505,8 +3505,8 @@ template `..^`*(a, b: untyped): untyped = a .. ^b template `..<`*(a, b: untyped): untyped = - ## a shortcut for 'a..pred(b)'. - a .. pred(b) + ## a shortcut for 'a .. (when b is BackwardsIndex: succ(b) else: pred(b))'. + a .. (when b is BackwardsIndex: succ(b) else: pred(b)) when defined(nimNewRoof): iterator `..<`*[T](a, b: T): T = diff --git a/tests/array/troofregression2.nim b/tests/array/troofregression2.nim new file mode 100644 index 000000000..78d9b9718 --- /dev/null +++ b/tests/array/troofregression2.nim @@ -0,0 +1,104 @@ +discard """ + output: '''OK +OK +OK +OK +OK +dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajs +dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdf +kgdchlfniambejop +fjpmholcibdgeakn +''' +""" + +import strutils, sequtils +# bug #6989 + +import typetraits + +type Dist = distinct int + +proc mypred[T: Ordinal](x: T): T = T(int(x)-1) +proc cons(x: int): Dist = Dist(x) + +var d: Dist + +template `^+`(s, i: untyped): untyped = + (when i is BackwardsIndex: s.len - int(i) else: int(i)) + +proc `...`*[T, U](a: T, b: U): HSlice[T, U] = + result.a = a + result.b = b + +proc `...`*[T](b: T): HSlice[int, T] = + result.b = b + +template `...<`*(a, b: untyped): untyped = + ## a shortcut for 'a..pred(b)'. + a ... pred(b) + +template check(a, b) = + if $a == b: echo "OK" + else: echo "Failure ", a, " != ", b + +check type(4 ...< 1), "HSlice[system.int, system.int]" + +check type(4 ...< ^1), "HSlice[system.int, system.BackwardsIndex]" +check type(4 ... pred(^1)), "HSlice[system.int, system.BackwardsIndex]" + +check type(4 ... mypred(8)), "HSlice[system.int, system.int]" + +check type(4 ... mypred(^1)), "HSlice[system.int, system.BackwardsIndex]" + +var rot = 8 + +proc bug(s: string): string = + result = s + result = result[result.len - rot .. ^1] & "__" & result[0 ..< ^rot] + +const testStr = "abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdflfdjkl" + +echo bug(testStr) +echo testStr[testStr.len - 8 .. testStr.len - 1] & "__" & testStr[0 .. testStr.len - pred(rot)] + + + +const + instructions = readFile("./inputs/16.txt").split(',') + programs = "abcdefghijklmnop" + +proc dance(dancers: string): string = + result = dancers + for instr in instructions: + let rem = instr[1 .. instr.high] + case instr[0] + of 's': + let rot = rem.parseInt + result = result[result.len - rot .. ^1] & result[0 ..< ^rot] + of 'x': + let + x = rem.split('/') + a = x[0].parseInt + b = x[1].parseInt + swap(result[a], result[b]) + of 'p': + let + a = result.find(rem[0]) + b = result.find(rem[^1]) + result[a] = rem[^1] + result[b] = rem[0] + else: discard + +proc longDance(dancers: string, iterations = 1_000_000_000): string = + var + dancers = dancers + seen = @[dancers] + for i in 1 .. iterations: + dancers = dancers.dance() + if dancers in seen: + return seen[iterations mod i] + seen.add(dancers) + + +echo dance(programs) +echo longDance(programs) |