Merge branch 'devel' of github.com:nim-lang/Nim into devel

This commit is contained in:
Araq
2018-06-26 01:35:12 +02:00
15 changed files with 248 additions and 52 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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,

View File

@@ -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
@@ -612,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:

View File

@@ -519,7 +519,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
@@ -558,7 +560,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:

View File

@@ -189,18 +189,19 @@ 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):
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
incl t.sym.flags, sfAnon
t.sym.flags = oldFlags
else:
c &= t.id
if t.len > 0 and t.sons[0] != nil:

View File

@@ -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))

View File

@@ -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.
##

View File

@@ -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"

View File

@@ -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)

View File

@@ -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)

58
tests/arithm/tnot.nim Normal file
View File

@@ -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

34
tests/arithm/tshl.nim Normal file
View File

@@ -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

View File

@@ -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

33
tests/types/t7905.nim Normal file
View File

@@ -0,0 +1,33 @@
discard """
output: '''
(member: "hello world")
(member: 123.456)
(member: "hello world", x: ...)
(member: 123.456, x: ...)
'''
"""
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)
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)