From 8508dc46c8c5b1535f42d2ade3687bb85d7037e7 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 19 Jun 2018 17:12:51 +0200 Subject: [PATCH 01/11] Fix minor codegen issue with static data types --- compiler/ccgexprs.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 82cc3a1fb0..0e8af5af5d 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -59,7 +59,7 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope = else: result = rope("NIM_NIL") of nkStrLit..nkTripleStrLit: - case skipTypes(ty, abstractVarRange).kind + case skipTypes(ty, abstractVarRange + {tyStatic}).kind of tyNil: result = genNilStringLiteral(p.module, n.info) of tyString: @@ -385,7 +385,7 @@ proc genDeepCopy(p: BProc; dest, src: TLoc) = else: addrLoc(p.config, a) - var ty = skipTypes(dest.t, abstractVarRange) + var ty = skipTypes(dest.t, abstractVarRange + {tyStatic}) case ty.kind of tyPtr, tyRef, tyProc, tyTuple, tyObject, tyArray: # XXX optimize this From fb62dd1fae7a405d80f0d4257ddb1f4d48e204f0 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 18 Jun 2018 14:30:18 +0200 Subject: [PATCH 02/11] Fix constant folding for shl/not Since the source and destination types are the same the result should be trimmed to fit. --- compiler/semfold.nim | 11 ++++++-- tests/arithm/tnot.nim | 58 +++++++++++++++++++++++++++++++++++++++++++ tests/arithm/tshl.nim | 34 +++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 tests/arithm/tnot.nim create mode 100644 tests/arithm/tshl.nim diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 10a223ea2b..eceb104700 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -211,7 +211,12 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode = of mUnaryMinusF64: result = newFloatNodeT(- getFloat(a), n, g) of mNot: result = newIntNodeT(1 - getInt(a), n, g) of mCard: result = newIntNodeT(nimsets.cardSet(g.config, a), n, g) - of mBitnotI: result = newIntNodeT(not getInt(a), n, g) + of mBitnotI: + case skipTypes(n.typ, abstractRange).kind + of tyUInt..tyUInt64: + result = newIntNodeT((not getInt(a)) and lastOrd(g.config, a.typ, fixedUnsigned=true), n, g) + else: + result = newIntNodeT(not getInt(a), n, g) of mLengthArray: result = newIntNodeT(lengthOrd(g.config, a.typ), n, g) of mLengthSeq, mLengthOpenArray, mXLenSeq, mLengthStr, mXLenStr: if a.kind == nkNilLit: @@ -250,8 +255,10 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode = of tyInt8: result = newIntNodeT(int8(getInt(a)) shl int8(getInt(b)), n, g) of tyInt16: result = newIntNodeT(int16(getInt(a)) shl int16(getInt(b)), n, g) of tyInt32: result = newIntNodeT(int32(getInt(a)) shl int32(getInt(b)), n, g) - of tyInt64, tyInt, tyUInt..tyUInt64: + of tyInt64, tyInt: result = newIntNodeT(`shl`(getInt(a), getInt(b)), n, g) + of tyUInt..tyUInt64: + result = newIntNodeT(`shl`(getInt(a), getInt(b)) and lastOrd(g.config, a.typ, fixedUnsigned=true), n, g) else: internalError(g.config, n.info, "constant folding for shl") of mShrI: case skipTypes(n.typ, abstractRange).kind diff --git a/tests/arithm/tnot.nim b/tests/arithm/tnot.nim new file mode 100644 index 0000000000..6a4877b2c6 --- /dev/null +++ b/tests/arithm/tnot.nim @@ -0,0 +1,58 @@ +discard """ + output: ''' +-5 +-5 +-5 +-5 +4 +4 +4 +4 +251 +65531 +4294967291 +18446744073709551611 +4 +4 +4 +4 +''' +""" + +# Signed types +block: + const t0: int8 = not 4 + const t1: int16 = not 4 + const t2: int32 = not 4 + const t3: int64 = not 4 + const t4: int8 = not -5 + const t5: int16 = not -5 + const t6: int32 = not -5 + const t7: int64 = not -5 + echo t0 + echo t1 + echo t2 + echo t3 + echo t4 + echo t5 + echo t6 + echo t7 + +# Unsigned types +block: + const t0: uint8 = not 4'u8 + const t1: uint16 = not 4'u16 + const t2: uint32 = not 4'u32 + const t3: uint64 = not 4'u64 + const t4: uint8 = not 251'u8 + const t5: uint16 = not 65531'u16 + const t6: uint32 = not 4294967291'u32 + const t7: uint64 = not 18446744073709551611'u64 + echo t0 + echo t1 + echo t2 + echo t3 + echo t4 + echo t5 + echo t6 + echo t7 diff --git a/tests/arithm/tshl.nim b/tests/arithm/tshl.nim new file mode 100644 index 0000000000..0aa46d021c --- /dev/null +++ b/tests/arithm/tshl.nim @@ -0,0 +1,34 @@ +discard """ + output: ''' +0 +0 +1 +1 +0 +0 +0 +1 +''' +""" + +# Signed types +block: + const t0: int8 = 1'i8 shl 8 + const t1: int16 = 1'i16 shl 16 + const t2: int32 = 1'i32 shl 32 + const t3: int64 = 1'i64 shl 64 + echo t0 + echo t1 + echo t2 + echo t3 + +# Unsigned types +block: + const t0: uint8 = 1'u8 shl 8 + const t1: uint16 = 1'u16 shl 16 + const t2: uint32 = 1'u32 shl 32 + const t3: uint64 = 1'u64 shl 64 + echo t0 + echo t1 + echo t2 + echo t3 From cc11aa9698e6537fd412bb64a3f99393bc51c90d Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 22 Jun 2018 03:19:30 +0200 Subject: [PATCH 03/11] varints module: critical bugfix --- lib/std/varints.nim | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/std/varints.nim b/lib/std/varints.nim index bfc1945fef..483d5c96cd 100644 --- a/lib/std/varints.nim +++ b/lib/std/varints.nim @@ -19,7 +19,7 @@ proc readVu64*(z: openArray[byte]; pResult: var uint64): int = return 1 if z[0] <= 248: if z.len < 2: return 0 - pResult = (uint64 z[0] - 241) * 256 + uint64 z[1] + 240 + pResult = (uint64 z[0] - 241) * 256 + z[1].uint64 + 240 return 2 if z.len < int(z[0]-246): return 0 if z[0] == 249: @@ -135,6 +135,13 @@ when isMainModule: if encodeZigzag(decodeZigzag(test)) != test: echo "Failure for ", test, " ", encodeZigzag(decodeZigzag(test)), " ", decodeZigzag(test) + for test in 0u64..300u64: + let wrLen = writeVu64(dest, test) + let rdLen = readVu64(dest, got) + assert wrLen == rdLen + if got != test: + echo "BUG! expected: ", test, " got: ", got, " z0: ", dest[0] + # check this also works for floats: for test in [0.0, 0.1, 2.0, +Inf, Nan, NegInf]: let t = cast[uint64](test) From af66258dca695d932e76ea31bdee2b2f185139cb Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 21 Jun 2018 22:21:24 +0200 Subject: [PATCH 04/11] Discriminate gensym'd type names in sigHash The root cause of #7905 lies in the codegen phase. The two template instantiations generate two different MyType types with different members but same t.sym.name leading the caching mechanism to confuse the two. Fixes #7905 --- compiler/sighashes.nim | 6 ++++-- tests/types/t7905.nim | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 tests/types/t7905.nim diff --git a/compiler/sighashes.nim b/compiler/sighashes.nim index 0b95387cd9..720d1848db 100644 --- a/compiler/sighashes.nim +++ b/compiler/sighashes.nim @@ -189,10 +189,11 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) = c.hashTypeSym(t.sym) else: c.hashSym(t.sym) - if sfAnon in t.sym.flags: + if {sfAnon, sfGenSym} * t.sym.flags != {}: # generated object names can be identical, so we need to # disambiguate furthermore by hashing the field types and names: # mild hack to prevent endless recursions (makes nimforum compile again): + let wasAnon = sfAnon in t.sym.flags excl t.sym.flags, sfAnon let n = t.n for i in 0 ..< n.len: @@ -200,7 +201,8 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) = let s = n[i].sym c.hashSym s c.hashType s.typ, flags - incl t.sym.flags, sfAnon + if wasAnon: + incl t.sym.flags, sfAnon else: c &= t.id if t.len > 0 and t.sons[0] != nil: diff --git a/tests/types/t7905.nim b/tests/types/t7905.nim new file mode 100644 index 0000000000..ddb3710395 --- /dev/null +++ b/tests/types/t7905.nim @@ -0,0 +1,18 @@ +discard """ + output: ''' +(member: "hello world") +(member: 123.456) +''' +""" + +template foobar(arg: typed): untyped = + type + MyType = object + member: type(arg) + + var myVar: MyType + myVar.member = arg + echo myVar + +foobar("hello world") +foobar(123.456'f64) From e39baf46fc523245a7d73b263808b944c6f225db Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 22 Jun 2018 15:09:35 +0200 Subject: [PATCH 05/11] Don't blow up with recursive objects --- compiler/sighashes.nim | 7 +++---- tests/types/t7905.nim | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/compiler/sighashes.nim b/compiler/sighashes.nim index 720d1848db..0bf2b84598 100644 --- a/compiler/sighashes.nim +++ b/compiler/sighashes.nim @@ -193,16 +193,15 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) = # generated object names can be identical, so we need to # disambiguate furthermore by hashing the field types and names: # mild hack to prevent endless recursions (makes nimforum compile again): - let wasAnon = sfAnon in t.sym.flags - excl t.sym.flags, sfAnon + let oldFlags = t.sym.flags + t.sym.flags = t.sym.flags - {sfAnon, sfGenSym} let n = t.n for i in 0 ..< n.len: assert n[i].kind == nkSym let s = n[i].sym c.hashSym s c.hashType s.typ, flags - if wasAnon: - incl t.sym.flags, sfAnon + t.sym.flags = oldFlags else: c &= t.id if t.len > 0 and t.sons[0] != nil: diff --git a/tests/types/t7905.nim b/tests/types/t7905.nim index ddb3710395..ef75bb86cf 100644 --- a/tests/types/t7905.nim +++ b/tests/types/t7905.nim @@ -2,6 +2,8 @@ discard """ output: ''' (member: "hello world") (member: 123.456) +(member: "hello world", x: ...) +(member: 123.456, x: ...) ''' """ @@ -16,3 +18,16 @@ template foobar(arg: typed): untyped = foobar("hello world") foobar(123.456'f64) + +template foobarRec(arg: typed): untyped = + type + MyType = object + member: type(arg) + x: ref MyType + + var myVar: MyType + myVar.member = arg + echo myVar + +foobarRec("hello world") +foobarRec(123.456'f64) From 7f0d7871eda6ec54a941b6a52f00ceb217bfe425 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 23 Jun 2018 13:37:35 +0200 Subject: [PATCH 06/11] Use the resolved typedesc in semVarOrLet By leaving the unsemanticized node in the AST we'd trip some passes like the Transf one as seen in #7936. --- compiler/semstmts.nim | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 3687e50e9c..3528d0155d 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -521,7 +521,9 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = localError(c.config, a.info, errWrongNumberOfVariables) b = newNodeI(nkVarTuple, a.info) newSons(b, length) - b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator + # keep type desc for doc generator + # NOTE: at the moment this is always ast.emptyNode, see parser.nim + b.sons[length-2] = a.sons[length-2] b.sons[length-1] = def addToVarSection(c, result, n, b) elif tup.kind == tyTuple and def.kind in {nkPar, nkTupleConstr} and @@ -560,7 +562,12 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = # keep documentation information: b.comment = a.comment addSon(b, newSymNode(v)) - addSon(b, a.sons[length-2]) # keep type desc for doc generator + # keep type desc for doc generator, but only if the user explicitly + # added it + if a.sons[length-2].kind != nkEmpty: + addSon(b, newNodeIT(nkType, a.info, typ)) + else: + addSon(b, a.sons[length-2]) addSon(b, copyTree(def)) addToVarSection(c, result, n, b) else: From 371f87e9626ce84a55b3d8e1aa1bc3a97ebcc91b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Nihlg=C3=A5rd?= Date: Sat, 23 Jun 2018 15:01:55 +0200 Subject: [PATCH 07/11] Change inconsistent paramaters in times.nim (#8091) --- lib/pure/times.nim | 47 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 7cecc31ab5..7fd60b818f 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -238,11 +238,11 @@ proc utcZoneInfoFromUtc(time: Time): ZonedTime {.tags: [], raises: [], benign .} proc utcZoneInfoFromTz(adjTime: Time): ZonedTime {.tags: [], raises: [], benign .} proc localZoneInfoFromUtc(time: Time): ZonedTime {.tags: [], raises: [], benign .} proc localZoneInfoFromTz(adjTime: Time): ZonedTime {.tags: [], raises: [], benign .} -proc initTime*(unix: int64, nanosecond: NanosecondRange): Time +proc initTime*(unix: int64, nanosecond: NanosecondRange): Time {.tags: [], raises: [], benign noSideEffect.} proc initDuration*(nanoseconds, microseconds, milliseconds, - seconds, minutes, hours, days, weeks: int64 = 0): Duration + seconds, minutes, hours, days, weeks: int64 = 0): Duration {.tags: [], raises: [], benign noSideEffect.} proc nanosecond*(time: Time): NanosecondRange = @@ -531,7 +531,7 @@ proc `$`*(dur: Duration): string = let quantity = numParts[unit] if quantity != 0.int64: parts.add(stringifyUnit(quantity, $unit)) - + result = humanizeParts(parts) proc `+`*(a, b: Duration): Duration {.operator.} = @@ -1243,23 +1243,23 @@ proc evaluateStaticInterval(interval: TimeInterval): Duration = minutes = interval.minutes, hours = interval.hours) -proc between*(startDt, endDt:DateTime): TimeInterval = +proc between*(startDt, endDt: DateTime): TimeInterval = ## Evaluate difference between two dates in ``TimeInterval`` format, so, it ## will be relative. ## - ## **Warning:** It's not recommended to use ``between`` for ``DateTime's`` in - ## different ``TimeZone's``. + ## **Warning:** It's not recommended to use ``between`` for ``DateTime's`` in + ## different ``TimeZone's``. ## ``a + between(a, b) == b`` is only guaranteed when ``a`` and ``b`` are in UTC. runnableExamples: - var a = initDateTime(year = 2018, month = Month(3), monthday = 25, + var a = initDateTime(year = 2018, month = Month(3), monthday = 25, hour = 0, minute = 59, second = 59, nanosecond = 1, zone = utc()).local - var b = initDateTime(year = 2018, month = Month(3), monthday = 25, + var b = initDateTime(year = 2018, month = Month(3), monthday = 25, hour = 1, minute = 1, second = 1, nanosecond = 0, zone = utc()).local doAssert between(a, b) == initTimeInterval( nanoseconds=999, milliseconds=999, microseconds=999, seconds=1, minutes=1) - + a = parse("2018-01-09T00:00:00+00:00", "yyyy-MM-dd'T'HH:mm:sszzz", utc()) b = parse("2018-01-10T23:00:00-02:00", "yyyy-MM-dd'T'HH:mm:sszzz") doAssert between(a, b) == initTimeInterval(hours=1, days=2) @@ -1526,7 +1526,6 @@ proc formatToken(dt: DateTime, token: string, buf: var string) = else: raise newException(ValueError, "Invalid format string: " & token) - proc format*(dt: DateTime, f: string): string {.tags: [].}= ## This procedure formats `dt` as specified by `f`. The following format ## specifiers are available: @@ -1601,18 +1600,14 @@ proc format*(dt: DateTime, f: string): string {.tags: [].}= inc(i) formatToken(dt, currentF, result) -proc format*(time: Time, f: string, zone_info: proc(t: Time): DateTime): string {.tags: [].} = - ## converts a `Time` value to a string representation. It will use format from +proc format*(time: Time, f: string, zone: Timezone = local()): string {.tags: [].} = + ## Converts a `Time` value to a string representation. It will use format from ## ``format(dt: DateTime, f: string)``. runnableExamples: - var dt = initDateTime(01, mJan, 1970, 00, 00, 00, local()) + var dt = initDateTime(01, mJan, 1970, 00, 00, 00, utc()) var tm = dt.toTime() - doAssert format(tm, "yyyy-MM-dd'T'HH:mm:ss", local) == "1970-01-01T00:00:00" - dt = initDateTime(01, mJan, 1970, 00, 00, 00, utc()) - tm = dt.toTime() - doAssert format(tm, "yyyy-MM-dd'T'HH:mm:ss", utc) == "1970-01-01T00:00:00" - - zone_info(time).format(f) + doAssert format(tm, "yyyy-MM-dd'T'HH:mm:ss", utc()) == "1970-01-01T00:00:00" + time.inZone(zone).format(f) proc `$`*(dt: DateTime): string {.tags: [], raises: [], benign.} = ## Converts a `DateTime` object to a string representation. @@ -1984,16 +1979,12 @@ proc countYearsAndDays*(daySpan: int): tuple[years: int, days: int] = proc toTimeInterval*(time: Time): TimeInterval = ## Converts a Time to a TimeInterval. ## - ## To be used when diffing times. + ## To be used when diffing times. Consider using `between` instead. runnableExamples: let a = fromUnix(10) - let dt = initDateTime(01, mJan, 1970, 00, 00, 00, local()) - doAssert a.toTimeInterval() == initTimeInterval( - years=1970, days=1, seconds=10, hours=convert( - Seconds, Hours, -dt.utcOffset - ) - ) - + let b = fromUnix(1_500_000_000) + let ti = b.toTimeInterval() - a.toTimeInterval() + doAssert a + ti == b var dt = time.local initTimeInterval(dt.nanosecond, 0, 0, dt.second, dt.minute, dt.hour, dt.monthday, 0, dt.month.ord - 1, dt.year) @@ -2150,7 +2141,7 @@ proc timeToTimeInterval*(t: Time): TimeInterval {.deprecated.} = t.toTimeInterval() proc getDayOfWeek*(day, month, year: int): WeekDay {.tags: [], raises: [], benign, deprecated.} = - ## **Deprecated since v0.18.0:** use + ## **Deprecated since v0.18.0:** use ## ``getDayOfWeek(monthday: MonthdayRange; month: Month; year: int)`` instead. getDayOfWeek(day, month.Month, year) From 059ddeee10a7b6e3805891b68205e01c045e038d Mon Sep 17 00:00:00 2001 From: Federico Ceratto Date: Sat, 23 Jun 2018 14:32:24 +0100 Subject: [PATCH 08/11] Minor doc fix --- lib/pure/httpclient.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 8530e4c42f..8b4fb0f8c1 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -1184,7 +1184,7 @@ proc request*(client: HttpClient | AsyncHttpClient, url: string, ## Connects to the hostname specified by the URL and performs a request ## using the custom method string specified by ``httpMethod``. ## - ## Connection will kept alive. Further requests on the same ``client`` to + ## Connection will be kept alive. Further requests on the same ``client`` to ## the same hostname will not require a new connection to be made. The ## connection can be closed by using the ``close`` procedure. ## From 4c2e712056b1e23d89be51f9cdcbfe573c399819 Mon Sep 17 00:00:00 2001 From: Kaushal Modi Date: Sun, 24 Jun 2018 03:53:20 -0400 Subject: [PATCH 09/11] Support setting foreground/background colors to terminal defaults (#8073) * Support setting foreground/background colors to terminal defaults Adds fgDefault to ForegroundColor and bgDefault to BackgroundColor enums. For Windows console, the default foreground color is assumed to be white, and the default background color black. * Add default fg/bg color caching for Windows Console --- lib/pure/terminal.nim | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 7ad243150a..ac41a0aad3 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -542,7 +542,9 @@ type fgBlue, ## blue fgMagenta, ## magenta fgCyan, ## cyan - fgWhite ## white + fgWhite, ## white + fg8Bit, ## 256-color (not supported, see ``enableTrueColors`` instead.) + fgDefault ## default terminal foreground color BackgroundColor* = enum ## terminal's background colors bgBlack = 40, ## black @@ -552,28 +554,40 @@ type bgBlue, ## blue bgMagenta, ## magenta bgCyan, ## cyan - bgWhite ## white + bgWhite, ## white + bg8Bit, ## 256-color (not supported, see ``enableTrueColors`` instead.) + bgDefault ## default terminal background color {.deprecated: [TForegroundColor: ForegroundColor, TBackgroundColor: BackgroundColor].} +when defined(windows): + var defaultForegroundColor, defaultBackgroundColor: int16 = 0xFFFF'i16 # Default to an invalid value 0xFFFF + proc setForegroundColor*(f: File, fg: ForegroundColor, bright=false) = ## Sets the terminal's foreground color. when defined(windows): let h = conHandle(f) var old = getAttributes(h) and not FOREGROUND_RGB + if defaultForegroundColor == 0xFFFF'i16: + defaultForegroundColor = old old = if bright: old or FOREGROUND_INTENSITY else: old and not(FOREGROUND_INTENSITY) const lookup: array[ForegroundColor, int] = [ - 0, + 0, # ForegroundColor enum with ordinal 30 (FOREGROUND_RED), (FOREGROUND_GREEN), (FOREGROUND_RED or FOREGROUND_GREEN), (FOREGROUND_BLUE), (FOREGROUND_RED or FOREGROUND_BLUE), (FOREGROUND_BLUE or FOREGROUND_GREEN), - (FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_RED)] - discard setConsoleTextAttribute(h, toU16(old or lookup[fg])) + (FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_RED), + 0, # fg8Bit not supported, see ``enableTrueColors`` instead. + 0] # unused + if fg == fgDefault: + discard setConsoleTextAttribute(h, toU16(old or defaultForegroundColor)) + else: + discard setConsoleTextAttribute(h, toU16(old or lookup[fg])) else: gFG = ord(fg) if bright: inc(gFG, 60) @@ -584,18 +598,25 @@ proc setBackgroundColor*(f: File, bg: BackgroundColor, bright=false) = when defined(windows): let h = conHandle(f) var old = getAttributes(h) and not BACKGROUND_RGB + if defaultBackgroundColor == 0xFFFF'i16: + defaultBackgroundColor = old old = if bright: old or BACKGROUND_INTENSITY else: old and not(BACKGROUND_INTENSITY) const lookup: array[BackgroundColor, int] = [ - 0, + 0, # BackgroundColor enum with ordinal 40 (BACKGROUND_RED), (BACKGROUND_GREEN), (BACKGROUND_RED or BACKGROUND_GREEN), (BACKGROUND_BLUE), (BACKGROUND_RED or BACKGROUND_BLUE), (BACKGROUND_BLUE or BACKGROUND_GREEN), - (BACKGROUND_BLUE or BACKGROUND_GREEN or BACKGROUND_RED)] - discard setConsoleTextAttribute(h, toU16(old or lookup[bg])) + (BACKGROUND_BLUE or BACKGROUND_GREEN or BACKGROUND_RED), + 0, # bg8Bit not supported, see ``enableTrueColors`` instead. + 0] # unused + if bg == bgDefault: + discard setConsoleTextAttribute(h, toU16(old or defaultBackgroundColor)) + else: + discard setConsoleTextAttribute(h, toU16(old or lookup[bg])) else: gBG = ord(bg) if bright: inc(gBG, 60) @@ -935,3 +956,6 @@ when not defined(testing) and isMainModule: stdout.styledWrite(fgGreen, "green text") echo "" echo "ordinary text" + stdout.styledWriteLine(fgRed, "red text ", styleBright, "bold red", fgDefault, " bold text") + stdout.styledWriteLine(bgYellow, "text in yellow bg", styleBright, " bold text in yellow bg", bgDefault, " bold text") + echo "ordinary text" From bfa3d62cc1a9485cc7030216f5859258131ea5bb Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 24 Jun 2018 15:13:34 +0200 Subject: [PATCH 10/11] More concept fixes Fixes #7705, #7703, #7702 --- compiler/semexprs.nim | 4 ++-- compiler/semfold.nim | 2 +- compiler/types.nim | 2 +- tests/concepts/treversable.nim | 31 +++++++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 tests/concepts/treversable.nim diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 9d7c493a7b..d7b5667b9a 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -271,7 +271,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = localError(c.config, n.info, errXExpectsTypeOrValue % opToStr[m]) else: n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType}) - var typ = skipTypes(n.sons[1].typ, abstractVarRange + {tyTypeDesc}) + var typ = skipTypes(n.sons[1].typ, abstractVarRange + {tyTypeDesc, tyUserTypeClassInst}) case typ.kind of tySequence, tyString, tyCString, tyOpenArray, tyVarargs: n.typ = getSysType(c.graph, n.info, tyInt) @@ -1261,7 +1261,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode = # make sure we don't evaluate generic macros/templates n.sons[0] = semExprWithType(c, n.sons[0], {efNoEvaluateGeneric}) - let arr = skipTypes(n.sons[0].typ, {tyGenericInst, + let arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyUserTypeClassInst, tyVar, tyLent, tyPtr, tyRef, tyAlias, tySink}) case arr.kind of tyArray, tyOpenArray, tyVarargs, tySequence, tyString, diff --git a/compiler/semfold.nim b/compiler/semfold.nim index eceb104700..2f495bc7f1 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -619,7 +619,7 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode = of mLow: result = newIntNodeT(firstOrd(g.config, n.sons[1].typ), n, g) of mHigh: - if skipTypes(n.sons[1].typ, abstractVar).kind notin + if skipTypes(n.sons[1].typ, abstractVar+{tyUserTypeClassInst}).kind notin {tySequence, tyString, tyCString, tyOpenArray, tyVarargs}: result = newIntNodeT(lastOrd(g.config, skipTypes(n[1].typ, abstractVar)), n, g) else: diff --git a/compiler/types.nim b/compiler/types.nim index 98343c6889..a1bdc77305 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -615,7 +615,7 @@ proc firstOrd*(conf: ConfigRef; t: PType): BiggestInt = else: assert(t.n.sons[0].kind == nkSym) result = t.n.sons[0].sym.position - of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic, tyInferred: + of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic, tyInferred, tyUserTypeClassInst: result = firstOrd(conf, lastSon(t)) of tyOrdinal: if t.len > 0: result = firstOrd(conf, lastSon(t)) diff --git a/tests/concepts/treversable.nim b/tests/concepts/treversable.nim new file mode 100644 index 0000000000..6ebc077d90 --- /dev/null +++ b/tests/concepts/treversable.nim @@ -0,0 +1,31 @@ +# issue 7705, 7703, 7702 +discard """ + output: ''' +z +e + ''' +""" + +type + Reversable*[T] = concept a + a[int] is T + a.high is int + a.len is int + a.low is int + +proc get[T](s: Reversable[T], n: int): T = + s[n] + +proc hi[T](s: Reversable[T]): int = + s.high + +proc lo[T](s: Reversable[T]): int = + s.low + +iterator reverse*[T](s: Reversable[T]): T = + assert hi(s) - lo(s) == len(s) - 1 + for z in hi(s).countdown(lo(s)): + yield s.get(z) + +for s in @["e", "z"].reverse: + echo s From 589d6bc8d81408df88298dd6cd3ee176d4bdbc46 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 25 Jun 2018 15:46:38 +0200 Subject: [PATCH 11/11] Warn the user if the specified verbosity level is wrong --- compiler/commands.nim | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/commands.nim b/compiler/commands.nim index 330504a76e..866405f9f5 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -606,7 +606,10 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; incl(conf.globalOptions, optRun) of "verbosity": expectArg(conf, switch, arg, pass, info) - conf.verbosity = parseInt(arg) + let verbosity = parseInt(arg) + if verbosity notin {0..3}: + localError(conf, info, "invalid verbosity level: '$1'" % arg) + conf.verbosity = verbosity conf.notes = NotesVerbosity[conf.verbosity] incl(conf.notes, conf.enableNotes) excl(conf.notes, conf.disableNotes)