parent
3ea3aa633d
commit
1efb5174f2
12 changed files with 290 additions and 171 deletions
|
|
@ -459,7 +459,7 @@ type
|
||||||
tfNotNil, # type cannot be 'nil'
|
tfNotNil, # type cannot be 'nil'
|
||||||
|
|
||||||
tfNeedsInit, # type constains a "not nil" constraint somewhere or some
|
tfNeedsInit, # type constains a "not nil" constraint somewhere or some
|
||||||
# other type so that it requires inititalization
|
# other type so that it requires initalization
|
||||||
tfVarIsPtr, # 'var' type is translated like 'ptr' even in C++ mode
|
tfVarIsPtr, # 'var' type is translated like 'ptr' even in C++ mode
|
||||||
tfHasMeta, # type contains "wildcard" sub-types such as generic params
|
tfHasMeta, # type contains "wildcard" sub-types such as generic params
|
||||||
# or other type classes
|
# or other type classes
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
if cmp < 0: best = z # x is better than the best so far
|
if cmp < 0: best = z # x is better than the best so far
|
||||||
elif cmp == 0: alt = z # x is as good as the best so far
|
elif cmp == 0: alt = z # x is as good as the best so far
|
||||||
else: discard
|
else: discard
|
||||||
#if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
|
#if sym.name.s == "cmp" and (n.info ?? "rstgen.nim") and n.info.line == 516:
|
||||||
# echo "Matches ", n.info, " ", typeToString(sym.typ)
|
# echo "Matches ", n.info, " ", typeToString(sym.typ)
|
||||||
# debug sym
|
# debug sym
|
||||||
# writeMatches(z)
|
# writeMatches(z)
|
||||||
|
|
|
||||||
|
|
@ -157,17 +157,40 @@ proc sumGeneric(t: PType): int =
|
||||||
result = ord(t.kind == tyGenericInvocation)
|
result = ord(t.kind == tyGenericInvocation)
|
||||||
for i in 0 .. <t.len: result += t.sons[i].sumGeneric
|
for i in 0 .. <t.len: result += t.sons[i].sumGeneric
|
||||||
break
|
break
|
||||||
of tyProc:
|
|
||||||
# proc matches proc better than 'stmt' to disambiguate 'spawn'
|
|
||||||
return 1
|
|
||||||
of tyGenericParam, tyExpr, tyStatic, tyStmt, tyTypeDesc: break
|
of tyGenericParam, tyExpr, tyStatic, tyStmt, tyTypeDesc: break
|
||||||
|
of tyBool, tyChar, tyEnum, tyObject, tyProc, tyPointer,
|
||||||
|
tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128,
|
||||||
|
tyUInt..tyUInt64:
|
||||||
|
return 1
|
||||||
else: return 0
|
else: return 0
|
||||||
|
|
||||||
|
#var ggDebug: bool
|
||||||
|
|
||||||
proc complexDisambiguation(a, b: PType): int =
|
proc complexDisambiguation(a, b: PType): int =
|
||||||
var x, y: int
|
# 'a' matches better if *every* argument matches better or equal than 'b'.
|
||||||
for i in 1 .. <a.len: x += a.sons[i].sumGeneric
|
var winner = 0
|
||||||
for i in 1 .. <b.len: y += b.sons[i].sumGeneric
|
for i in 1 .. <min(a.len, b.len):
|
||||||
result = x - y
|
let x = a.sons[i].sumGeneric
|
||||||
|
let y = b.sons[i].sumGeneric
|
||||||
|
#if ggDebug:
|
||||||
|
# echo "came her ", typeToString(a.sons[i]), " ", typeToString(b.sons[i])
|
||||||
|
if x != y:
|
||||||
|
if winner == 0:
|
||||||
|
if x > y: winner = 1
|
||||||
|
else: winner = -1
|
||||||
|
elif x > y:
|
||||||
|
if winner != 1:
|
||||||
|
# contradiction
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
if winner != -1:
|
||||||
|
return 0
|
||||||
|
result = winner
|
||||||
|
when false:
|
||||||
|
var x, y: int
|
||||||
|
for i in 1 .. <a.len: x += a.sons[i].sumGeneric
|
||||||
|
for i in 1 .. <b.len: y += b.sons[i].sumGeneric
|
||||||
|
result = x - y
|
||||||
when false:
|
when false:
|
||||||
proc betterThan(a, b: PType): bool {.inline.} = a.sumGeneric > b.sumGeneric
|
proc betterThan(a, b: PType): bool {.inline.} = a.sumGeneric > b.sumGeneric
|
||||||
|
|
||||||
|
|
@ -338,7 +361,8 @@ proc minRel(a, b: TTypeRelation): TTypeRelation =
|
||||||
|
|
||||||
proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
result = isNone
|
result = isNone
|
||||||
if sameType(f, a): result = isEqual
|
if sameType(f, a):
|
||||||
|
result = isEqual
|
||||||
elif sonsLen(a) == sonsLen(f):
|
elif sonsLen(a) == sonsLen(f):
|
||||||
result = isEqual
|
result = isEqual
|
||||||
let firstField = if f.kind == tyTuple: 0
|
let firstField = if f.kind == tyTuple: 0
|
||||||
|
|
@ -380,17 +404,17 @@ proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
# no luck resolving the type, so the inference fails
|
# no luck resolving the type, so the inference fails
|
||||||
return isNone
|
return isNone
|
||||||
let reverseRel = typeRel(c, a, f)
|
let reverseRel = typeRel(c, a, f)
|
||||||
if reverseRel == isGeneric:
|
if reverseRel >= isGeneric:
|
||||||
result = isInferred
|
result = isInferred
|
||||||
inc c.genericMatches
|
#inc c.genericMatches
|
||||||
else:
|
else:
|
||||||
result = typeRel(c, f, a)
|
result = typeRel(c, f, a)
|
||||||
|
|
||||||
if result <= isSubtype or inconsistentVarTypes(f, a):
|
if result <= isSubtype or inconsistentVarTypes(f, a):
|
||||||
result = isNone
|
result = isNone
|
||||||
|
|
||||||
if result == isEqual:
|
#if result == isEqual:
|
||||||
inc c.exactMatches
|
# inc c.exactMatches
|
||||||
|
|
||||||
proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
case a.kind
|
case a.kind
|
||||||
|
|
@ -433,6 +457,7 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
return isNone
|
return isNone
|
||||||
when useEffectSystem:
|
when useEffectSystem:
|
||||||
if not compatibleEffects(f, a): return isNone
|
if not compatibleEffects(f, a): return isNone
|
||||||
|
|
||||||
of tyNil:
|
of tyNil:
|
||||||
result = f.allowsNil
|
result = f.allowsNil
|
||||||
of tyIter:
|
of tyIter:
|
||||||
|
|
@ -590,10 +615,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
return typeRel(c, f, lastSon(a))
|
return typeRel(c, f, lastSon(a))
|
||||||
|
|
||||||
template bindingRet(res) =
|
template bindingRet(res) =
|
||||||
when res == isGeneric:
|
if doBind:
|
||||||
if doBind:
|
let bound = aOrig.skipTypes({tyRange}).skipIntLit
|
||||||
let bound = aOrig.skipTypes({tyRange}).skipIntLit
|
if doBind: put(c.bindings, f, bound)
|
||||||
if doBind: put(c.bindings, f, bound)
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
template considerPreviousT(body: stmt) {.immediate.} =
|
template considerPreviousT(body: stmt) {.immediate.} =
|
||||||
|
|
@ -605,20 +629,21 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
of tyOr:
|
of tyOr:
|
||||||
# seq[int|string] vs seq[number]
|
# seq[int|string] vs seq[number]
|
||||||
# both int and string must match against number
|
# both int and string must match against number
|
||||||
|
# but ensure that '[T: A|A]' matches as good as '[T: A]' (bug #2219):
|
||||||
|
result = isGeneric
|
||||||
for branch in a.sons:
|
for branch in a.sons:
|
||||||
if typeRel(c, f, branch, false) == isNone:
|
let x = typeRel(c, f, branch, false)
|
||||||
return isNone
|
if x == isNone: return isNone
|
||||||
|
if x < result: result = x
|
||||||
return isGeneric
|
|
||||||
|
|
||||||
of tyAnd:
|
of tyAnd:
|
||||||
# seq[Sortable and Iterable] vs seq[Sortable]
|
# seq[Sortable and Iterable] vs seq[Sortable]
|
||||||
# only one match is enough
|
# only one match is enough
|
||||||
for branch in a.sons:
|
for branch in a.sons:
|
||||||
if typeRel(c, f, branch, false) != isNone:
|
let x = typeRel(c, f, branch, false)
|
||||||
return isGeneric
|
if x != isNone:
|
||||||
|
return if x >= isGeneric: isGeneric else: x
|
||||||
return isNone
|
result = isNone
|
||||||
|
|
||||||
of tyNot:
|
of tyNot:
|
||||||
case f.kind
|
case f.kind
|
||||||
|
|
@ -781,11 +806,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
inc(c.inheritancePenalty, depth)
|
inc(c.inheritancePenalty, depth)
|
||||||
result = isSubtype
|
result = isSubtype
|
||||||
of tyDistinct:
|
of tyDistinct:
|
||||||
if (a.kind == tyDistinct) and sameDistinctTypes(f, a): result = isEqual
|
if a.kind == tyDistinct and sameDistinctTypes(f, a): result = isEqual
|
||||||
elif c.coerceDistincts: result = typeRel(c, f.base, a)
|
elif c.coerceDistincts: result = typeRel(c, f.base, a)
|
||||||
of tySet:
|
of tySet:
|
||||||
if a.kind == tySet:
|
if a.kind == tySet:
|
||||||
if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
|
if f.sons[0].kind != tyGenericParam and a.sons[0].kind == tyEmpty:
|
||||||
result = isSubtype
|
result = isSubtype
|
||||||
else:
|
else:
|
||||||
result = typeRel(c, f.sons[0], a.sons[0])
|
result = typeRel(c, f.sons[0], a.sons[0])
|
||||||
|
|
@ -865,7 +890,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
result = typeRel(c, ff, aa)
|
result = typeRel(c, ff, aa)
|
||||||
if result == isNone: return
|
if result == isNone: return
|
||||||
if ff.kind == tyRange and result != isEqual: return isNone
|
if ff.kind == tyRange and result != isEqual: return isNone
|
||||||
result = isGeneric
|
#result = isGeneric
|
||||||
# XXX See bug #2220. A[int] should match A[int] better than some generic X
|
# XXX See bug #2220. A[int] should match A[int] better than some generic X
|
||||||
else:
|
else:
|
||||||
result = typeRel(c, lastSon(f), a)
|
result = typeRel(c, lastSon(f), a)
|
||||||
|
|
@ -904,18 +929,23 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
of tyAnd:
|
of tyAnd:
|
||||||
considerPreviousT:
|
considerPreviousT:
|
||||||
for branch in f.sons:
|
for branch in f.sons:
|
||||||
if typeRel(c, branch, aOrig) < isSubtype:
|
let x = typeRel(c, branch, aOrig)
|
||||||
return isNone
|
if x < isSubtype: return isNone
|
||||||
|
# 'and' implies minimum matching result:
|
||||||
bindingRet isGeneric
|
if x < result: result = x
|
||||||
|
bindingRet result
|
||||||
|
|
||||||
of tyOr:
|
of tyOr:
|
||||||
considerPreviousT:
|
considerPreviousT:
|
||||||
|
result = isNone
|
||||||
for branch in f.sons:
|
for branch in f.sons:
|
||||||
if typeRel(c, branch, aOrig) >= isSubtype:
|
let x = typeRel(c, branch, aOrig)
|
||||||
bindingRet isGeneric
|
# 'or' implies maximum matching result:
|
||||||
|
if x > result: result = x
|
||||||
return isNone
|
if result >= isSubtype:
|
||||||
|
bindingRet result
|
||||||
|
else:
|
||||||
|
result = isNone
|
||||||
|
|
||||||
of tyNot:
|
of tyNot:
|
||||||
considerPreviousT:
|
considerPreviousT:
|
||||||
|
|
@ -975,6 +1005,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
internalAssert a.sons != nil and a.sons.len > 0
|
internalAssert a.sons != nil and a.sons.len > 0
|
||||||
c.typedescMatched = true
|
c.typedescMatched = true
|
||||||
result = typeRel(c, f.base, a.skipTypes({tyGenericParam, tyTypeDesc}))
|
result = typeRel(c, f.base, a.skipTypes({tyGenericParam, tyTypeDesc}))
|
||||||
|
if result > isGeneric: result = isGeneric
|
||||||
else:
|
else:
|
||||||
result = isNone
|
result = isNone
|
||||||
else:
|
else:
|
||||||
|
|
@ -998,12 +1029,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
return isNone
|
return isNone
|
||||||
if doBind:
|
if doBind:
|
||||||
put(c.bindings, f, concrete)
|
put(c.bindings, f, concrete)
|
||||||
|
elif result > isGeneric:
|
||||||
|
result = isGeneric
|
||||||
elif a.kind == tyEmpty:
|
elif a.kind == tyEmpty:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
elif x.kind == tyGenericParam:
|
elif x.kind == tyGenericParam:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
else:
|
else:
|
||||||
result = typeRel(c, x, a) # check if it fits
|
result = typeRel(c, x, a) # check if it fits
|
||||||
|
if result > isGeneric: result = isGeneric
|
||||||
|
|
||||||
of tyStatic:
|
of tyStatic:
|
||||||
let prev = PType(idTableGet(c.bindings, f))
|
let prev = PType(idTableGet(c.bindings, f))
|
||||||
|
|
@ -1220,8 +1254,9 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
of isConvertible, isIntConv: inc(m.convMatches)
|
of isConvertible, isIntConv: inc(m.convMatches)
|
||||||
of isSubtype, isSubrange: inc(m.subtypeMatches)
|
of isSubtype, isSubrange: inc(m.subtypeMatches)
|
||||||
of isGeneric, isInferred: inc(m.genericMatches)
|
of isGeneric, isInferred: inc(m.genericMatches)
|
||||||
of isInferredConvertible: inc(m.genericMatches); inc(m.convMatches)
|
|
||||||
of isFromIntLit: inc(m.intConvMatches, 256)
|
of isFromIntLit: inc(m.intConvMatches, 256)
|
||||||
|
of isInferredConvertible:
|
||||||
|
inc(m.convMatches)
|
||||||
of isEqual: inc(m.exactMatches)
|
of isEqual: inc(m.exactMatches)
|
||||||
of isNone: discard
|
of isNone: discard
|
||||||
|
|
||||||
|
|
@ -1255,9 +1290,11 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
result = implicitConv(nkHiddenSubConv, f, arg, m, c)
|
result = implicitConv(nkHiddenSubConv, f, arg, m, c)
|
||||||
of isSubrange:
|
of isSubrange:
|
||||||
inc(m.subtypeMatches)
|
inc(m.subtypeMatches)
|
||||||
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
|
if f.kind == tyVar:
|
||||||
|
result = arg
|
||||||
|
else:
|
||||||
|
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
|
||||||
of isInferred, isInferredConvertible:
|
of isInferred, isInferredConvertible:
|
||||||
inc(m.genericMatches)
|
|
||||||
if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds:
|
if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds:
|
||||||
result = c.semInferredLambda(c, m.bindings, arg)
|
result = c.semInferredLambda(c, m.bindings, arg)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1266,6 +1303,8 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
if r == isInferredConvertible:
|
if r == isInferredConvertible:
|
||||||
inc(m.convMatches)
|
inc(m.convMatches)
|
||||||
result = implicitConv(nkHiddenStdConv, f, result, m, c)
|
result = implicitConv(nkHiddenStdConv, f, result, m, c)
|
||||||
|
else:
|
||||||
|
inc(m.genericMatches)
|
||||||
of isGeneric:
|
of isGeneric:
|
||||||
inc(m.genericMatches)
|
inc(m.genericMatches)
|
||||||
if arg.typ == nil:
|
if arg.typ == nil:
|
||||||
|
|
@ -1331,7 +1370,16 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
|
||||||
for i in countup(0, sonsLen(arg) - 1):
|
for i in countup(0, sonsLen(arg) - 1):
|
||||||
if arg.sons[i].sym.kind in {skProc, skMethod, skConverter}+skIterators:
|
if arg.sons[i].sym.kind in {skProc, skMethod, skConverter}+skIterators:
|
||||||
copyCandidate(z, m)
|
copyCandidate(z, m)
|
||||||
|
z.callee = arg.sons[i].typ
|
||||||
|
z.calleeSym = arg.sons[i].sym
|
||||||
|
#if arg.sons[i].sym.name.s == "cmp":
|
||||||
|
# ggDebug = true
|
||||||
|
# echo "CALLLEEEEEEEE ", typeToString(z.callee)
|
||||||
var r = typeRel(z, f, arg.sons[i].typ)
|
var r = typeRel(z, f, arg.sons[i].typ)
|
||||||
|
#if arg.sons[i].sym.name.s == "cmp": # and arg.info.line == 606:
|
||||||
|
# echo "M ", r, " ", arg.info, " ", typeToString(arg.sons[i].sym.typ)
|
||||||
|
# debug arg.sons[i].sym
|
||||||
|
# writeMatches(z)
|
||||||
if r != isNone:
|
if r != isNone:
|
||||||
case x.state
|
case x.state
|
||||||
of csEmpty, csNoMatch:
|
of csEmpty, csNoMatch:
|
||||||
|
|
@ -1644,7 +1692,7 @@ tests:
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
var c: TCandidate
|
var c: TCandidate
|
||||||
InitCandidate(nil, c, nil)
|
initCandidate(nil, c, nil)
|
||||||
|
|
||||||
template yes(x, y) =
|
template yes(x, y) =
|
||||||
test astToStr(x) & " is " & astToStr(y):
|
test astToStr(x) & " is " & astToStr(y):
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ when defined(Windows):
|
||||||
while i < password.len:
|
while i < password.len:
|
||||||
x = runeLenAt(password, i)
|
x = runeLenAt(password, i)
|
||||||
inc i, x
|
inc i, x
|
||||||
password.setLen(password.len - x)
|
password.setLen(password.len - x)
|
||||||
else:
|
else:
|
||||||
password.add(toUTF8(c.Rune))
|
password.add(toUTF8(c.Rune))
|
||||||
stdout.write "\n"
|
stdout.write "\n"
|
||||||
|
|
|
||||||
|
|
@ -75,11 +75,12 @@ const
|
||||||
proc lowerBound*[T](a: openArray[T], key: T, cmp: proc(x,y: T): int {.closure.}): int =
|
proc lowerBound*[T](a: openArray[T], key: T, cmp: proc(x,y: T): int {.closure.}): int =
|
||||||
## same as binarySearch except that if key is not in `a` then this
|
## same as binarySearch except that if key is not in `a` then this
|
||||||
## returns the location where `key` would be if it were. In other
|
## returns the location where `key` would be if it were. In other
|
||||||
## words if you have a sorted sequence and you call insert(thing, elm, lowerBound(thing, elm))
|
## words if you have a sorted sequence and you call
|
||||||
## the sequence will still be sorted
|
## insert(thing, elm, lowerBound(thing, elm))
|
||||||
|
## the sequence will still be sorted.
|
||||||
##
|
##
|
||||||
## `cmp` is the comparator function to use, the expected return values are the same as
|
## `cmp` is the comparator function to use, the expected return values are
|
||||||
## that of system.cmp
|
## the same as that of system.cmp.
|
||||||
##
|
##
|
||||||
## example::
|
## example::
|
||||||
##
|
##
|
||||||
|
|
@ -187,7 +188,8 @@ proc sort*[T](a: var openArray[T],
|
||||||
dec(m, s*2)
|
dec(m, s*2)
|
||||||
s = s*2
|
s = s*2
|
||||||
|
|
||||||
proc sorted*[T](a: openArray[T], cmp: proc(x, y: T): int {.closure.}, order = SortOrder.Ascending): seq[T] =
|
proc sorted*[T](a: openArray[T], cmp: proc(x, y: T): int {.closure.},
|
||||||
|
order = SortOrder.Ascending): seq[T] =
|
||||||
## returns `a` sorted by `cmp` in the specified `order`.
|
## returns `a` sorted by `cmp` in the specified `order`.
|
||||||
result = newSeq[T](a.len)
|
result = newSeq[T](a.len)
|
||||||
for i in 0 .. a.high:
|
for i in 0 .. a.high:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
# Bug #2022
|
# Bug #2022
|
||||||
|
|
||||||
|
discard """
|
||||||
|
output: '''@[97, 45]
|
||||||
|
@[true, false]
|
||||||
|
@[false, false]'''
|
||||||
|
"""
|
||||||
|
|
||||||
## The goal of this snippet is to provide and test a construct for general-
|
## The goal of this snippet is to provide and test a construct for general-
|
||||||
## purpose, random-access mapping. I use an AST-manipulation-based approach
|
## purpose, random-access mapping. I use an AST-manipulation-based approach
|
||||||
## because it's more efficient than using procedure pointers and less
|
## because it's more efficient than using procedure pointers and less
|
||||||
|
|
@ -31,6 +37,7 @@ type Mapped[Input; predicate: static[string]] = object
|
||||||
input: Input
|
input: Input
|
||||||
|
|
||||||
macro map(input, predicate: expr): expr =
|
macro map(input, predicate: expr): expr =
|
||||||
|
let predicate = callsite()[2]
|
||||||
newNimNode(nnkObjConstr).add(
|
newNimNode(nnkObjConstr).add(
|
||||||
newNimNode(nnkBracketExpr).add(
|
newNimNode(nnkBracketExpr).add(
|
||||||
ident"Mapped",
|
ident"Mapped",
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
|
discard """
|
||||||
|
output: '''another number: 123
|
||||||
|
yay'''
|
||||||
|
"""
|
||||||
|
|
||||||
# Test overloading of procs when used as function pointers
|
# Test overloading of procs when used as function pointers
|
||||||
|
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
proc parseInt(x: float): int {.noSideEffect.} = nil
|
proc parseInt(x: float): int {.noSideEffect.} = discard
|
||||||
proc parseInt(x: bool): int {.noSideEffect.} = nil
|
proc parseInt(x: bool): int {.noSideEffect.} = discard
|
||||||
proc parseInt(x: float32): int {.noSideEffect.} = nil
|
proc parseInt(x: float32): int {.noSideEffect.} = discard
|
||||||
proc parseInt(x: int8): int {.noSideEffect.} = nil
|
proc parseInt(x: int8): int {.noSideEffect.} = discard
|
||||||
proc parseInt(x: TFile): int {.noSideEffect.} = nil
|
proc parseInt(x: TFile): int {.noSideEffect.} = discard
|
||||||
proc parseInt(x: char): int {.noSideEffect.} = nil
|
proc parseInt(x: char): int {.noSideEffect.} = discard
|
||||||
proc parseInt(x: int16): int {.noSideEffect.} = nil
|
proc parseInt(x: int16): int {.noSideEffect.} = discard
|
||||||
|
|
||||||
proc parseInt[T](x: T): int = echo x; 34
|
proc parseInt[T](x: T): int = echo x; 34
|
||||||
|
|
||||||
|
|
@ -22,9 +27,10 @@ var
|
||||||
proc takeParseInt(x: proc (y: string): int {.noSideEffect.}): int =
|
proc takeParseInt(x: proc (y: string): int {.noSideEffect.}): int =
|
||||||
result = x("123")
|
result = x("123")
|
||||||
|
|
||||||
echo "Give a list of numbers (separated by spaces): "
|
if false:
|
||||||
var x = stdin.readline.split.map(parseInt).max
|
echo "Give a list of numbers (separated by spaces): "
|
||||||
echo x, " is the maximum!"
|
var x = stdin.readline.split.map(parseInt).max
|
||||||
|
echo x, " is the maximum!"
|
||||||
echo "another number: ", takeParseInt(parseInt)
|
echo "another number: ", takeParseInt(parseInt)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
22
tests/overload/tprefer_specialized_generic.nim
Normal file
22
tests/overload/tprefer_specialized_generic.nim
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
discard """
|
||||||
|
output: '''ref ref T ptr S'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
proc foo[T](x: T) =
|
||||||
|
echo "only T"
|
||||||
|
|
||||||
|
proc foo[T](x: ref T) =
|
||||||
|
echo "ref T"
|
||||||
|
|
||||||
|
proc foo[T, S](x: ref ref T; y: ptr S) =
|
||||||
|
echo "ref ref T ptr S"
|
||||||
|
|
||||||
|
proc foo[T, S](x: ref T; y: ptr S) =
|
||||||
|
echo "ref T ptr S"
|
||||||
|
|
||||||
|
proc foo[T](x: ref T; default = 0) =
|
||||||
|
echo "ref T; default"
|
||||||
|
|
||||||
|
var x: ref ref int
|
||||||
|
var y: ptr ptr int
|
||||||
|
foo(x, y)
|
||||||
|
|
@ -1,17 +1,42 @@
|
||||||
discard """
|
discard """
|
||||||
output: "Version 2 was called."
|
output: '''Version 2 was called.
|
||||||
disabled: true
|
This has the highest precedence.
|
||||||
|
This has the second-highest precedence.
|
||||||
|
This has the lowest precedence.'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# bug #2220
|
# bug #2220
|
||||||
|
when true:
|
||||||
|
type A[T] = object
|
||||||
|
type B = A[int]
|
||||||
|
|
||||||
type A[T] = object
|
proc q[X](x: X) =
|
||||||
type B = A[int]
|
echo "Version 1 was called."
|
||||||
|
|
||||||
proc p[X](x: X) =
|
proc q(x: B) =
|
||||||
echo "Version 1 was called."
|
echo "Version 2 was called."
|
||||||
|
|
||||||
proc p(x: B) =
|
q(B()) # This call reported as ambiguous.
|
||||||
echo "Version 2 was called."
|
|
||||||
|
|
||||||
p(B()) # This call reported as ambiguous.
|
# bug #2219
|
||||||
|
template testPred(a: expr) =
|
||||||
|
block:
|
||||||
|
type A = object of RootObj
|
||||||
|
type B = object of A
|
||||||
|
type SomeA = A|A # A hack to make "A" a typeclass.
|
||||||
|
|
||||||
|
when a >= 3:
|
||||||
|
proc p[X](x: X) =
|
||||||
|
echo "This has the highest precedence."
|
||||||
|
when a >= 2:
|
||||||
|
proc p[X: A](x: X) =
|
||||||
|
echo "This has the second-highest precedence."
|
||||||
|
when a >= 1:
|
||||||
|
proc p[X: SomeA](x: X) =
|
||||||
|
echo "This has the lowest precedence."
|
||||||
|
|
||||||
|
p(B())
|
||||||
|
|
||||||
|
testPred(3)
|
||||||
|
testPred(2)
|
||||||
|
testPred(1)
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,12 @@ import algorithm
|
||||||
# bug #1657
|
# bug #1657
|
||||||
var modules = @["hi", "ho", "ha", "huu"]
|
var modules = @["hi", "ho", "ha", "huu"]
|
||||||
sort(modules, system.cmp)
|
sort(modules, system.cmp)
|
||||||
|
|
||||||
|
type
|
||||||
|
MyType = object
|
||||||
|
x: string
|
||||||
|
|
||||||
|
proc cmp(a, b: MyType): int = cmp(a.x, b.x)
|
||||||
|
|
||||||
|
var modulesB = @[MyType(x: "ho"), MyType(x: "ha")]
|
||||||
|
sort(modulesB, cmp)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
discard """
|
discard """
|
||||||
errormsg: "'"
|
errormsg: "'"
|
||||||
file: "sequtils.nim"
|
file: "sequtils.nim"
|
||||||
line: 416
|
line: 435
|
||||||
"""
|
"""
|
||||||
# unfortunately our tester doesn't support multiple lines of compiler
|
# unfortunately our tester doesn't support multiple lines of compiler
|
||||||
# error messages yet...
|
# error messages yet...
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue