Merge remote-tracking branch 'upstream/devel' into devel
This commit is contained in:
commit
efe183861c
13 changed files with 252 additions and 113 deletions
|
|
@ -399,6 +399,7 @@ const
|
||||||
tyPureObject* = tyTuple
|
tyPureObject* = tyTuple
|
||||||
GcTypeKinds* = {tyRef, tySequence, tyString}
|
GcTypeKinds* = {tyRef, tySequence, tyString}
|
||||||
tyError* = tyProxy # as an errornous node should match everything
|
tyError* = tyProxy # as an errornous node should match everything
|
||||||
|
tyUnknown* = tyFromExpr
|
||||||
|
|
||||||
tyUnknownTypes* = {tyError, tyFromExpr}
|
tyUnknownTypes* = {tyError, tyFromExpr}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -277,16 +277,14 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
|
||||||
styleCheckUse(n.sons[0].info, finalCallee)
|
styleCheckUse(n.sons[0].info, finalCallee)
|
||||||
if finalCallee.ast == nil:
|
if finalCallee.ast == nil:
|
||||||
internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
|
internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
|
||||||
|
if x.hasFauxMatch:
|
||||||
|
result = x.call
|
||||||
|
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
||||||
|
if containsGenericType(result.typ) or x.fauxMatch == tyUnknown:
|
||||||
|
result.typ = newTypeS(x.fauxMatch, c)
|
||||||
|
return
|
||||||
if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty:
|
if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty:
|
||||||
# a generic proc!
|
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
|
||||||
if not x.proxyMatch:
|
|
||||||
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
|
|
||||||
else:
|
|
||||||
result = x.call
|
|
||||||
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
|
||||||
result.typ = finalCallee.typ.sons[0]
|
|
||||||
if containsGenericType(result.typ): result.typ = errorType(c)
|
|
||||||
return
|
|
||||||
result = x.call
|
result = x.call
|
||||||
instGenericConvertersSons(c, result, x)
|
instGenericConvertersSons(c, result, x)
|
||||||
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,7 @@ proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
|
||||||
|
|
||||||
template rangeHasStaticIf*(t: PType): bool =
|
template rangeHasStaticIf*(t: PType): bool =
|
||||||
# this accepts the ranges's node
|
# this accepts the ranges's node
|
||||||
t.n[1].kind == nkStaticExpr
|
t.n != nil and t.n.len > 1 and t.n[1].kind == nkStaticExpr
|
||||||
|
|
||||||
template getStaticTypeFromRange*(t: PType): PType =
|
template getStaticTypeFromRange*(t: PType): PType =
|
||||||
t.n[1][0][1].typ
|
t.n[1][0][1].typ
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ proc semConv(c: PContext, n: PNode): PNode =
|
||||||
return n
|
return n
|
||||||
|
|
||||||
result = newNodeI(nkConv, n.info)
|
result = newNodeI(nkConv, n.info)
|
||||||
var targetType = semTypeNode(c, n.sons[0], nil)
|
var targetType = semTypeNode(c, n.sons[0], nil).skipTypes({tyTypeDesc})
|
||||||
maybeLiftType(targetType, c, n[0].info)
|
maybeLiftType(targetType, c, n[0].info)
|
||||||
result.addSon copyTree(n.sons[0])
|
result.addSon copyTree(n.sons[0])
|
||||||
var op = semExprWithType(c, n.sons[1])
|
var op = semExprWithType(c, n.sons[1])
|
||||||
|
|
@ -780,7 +780,6 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
|
if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
|
||||||
elif t != nil and t.kind == tyTypeDesc:
|
elif t != nil and t.kind == tyTypeDesc:
|
||||||
if n.len == 1: return semObjConstr(c, n, flags)
|
if n.len == 1: return semObjConstr(c, n, flags)
|
||||||
let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
|
|
||||||
return semConv(c, n)
|
return semConv(c, n)
|
||||||
else:
|
else:
|
||||||
result = overloadedCallOpr(c, n)
|
result = overloadedCallOpr(c, n)
|
||||||
|
|
@ -928,7 +927,6 @@ proc readTypeParameter(c: PContext, typ: PType,
|
||||||
let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias
|
let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias
|
||||||
else: (internalAssert(typ.kind == tyCompositeTypeClass);
|
else: (internalAssert(typ.kind == tyCompositeTypeClass);
|
||||||
typ.sons[1].skipGenericAlias)
|
typ.sons[1].skipGenericAlias)
|
||||||
#debug ty
|
|
||||||
let tbody = ty.sons[0]
|
let tbody = ty.sons[0]
|
||||||
for s in countup(0, tbody.len-2):
|
for s in countup(0, tbody.len-2):
|
||||||
let tParam = tbody.sons[s]
|
let tParam = tbody.sons[s]
|
||||||
|
|
|
||||||
|
|
@ -1262,10 +1262,14 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
n.sons[i] = semExpr(c, n.sons[i])
|
n.sons[i] = semExpr(c, n.sons[i])
|
||||||
if c.inTypeClass > 0 and n[i].typ != nil and n[i].typ.kind == tyBool:
|
if c.inTypeClass > 0 and n[i].typ != nil:
|
||||||
let verdict = semConstExpr(c, n[i])
|
case n[i].typ.kind
|
||||||
if verdict.intVal == 0:
|
of tyBool:
|
||||||
localError(result.info, "type class predicate failed")
|
let verdict = semConstExpr(c, n[i])
|
||||||
|
if verdict.intVal == 0:
|
||||||
|
localError(result.info, "type class predicate failed")
|
||||||
|
of tyUnknown: continue
|
||||||
|
else: discard
|
||||||
if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]):
|
if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]):
|
||||||
voidContext = true
|
voidContext = true
|
||||||
n.typ = enforceVoidContext
|
n.typ = enforceVoidContext
|
||||||
|
|
|
||||||
|
|
@ -225,11 +225,10 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
|
||||||
elif e.kind == nkSym and e.typ.kind == tyStatic:
|
elif e.kind == nkSym and e.typ.kind == tyStatic:
|
||||||
if e.sym.ast != nil:
|
if e.sym.ast != nil:
|
||||||
return semArrayIndex(c, e.sym.ast)
|
return semArrayIndex(c, e.sym.ast)
|
||||||
internalAssert c.inGenericContext > 0
|
|
||||||
if not isOrdinalType(e.typ.lastSon):
|
if not isOrdinalType(e.typ.lastSon):
|
||||||
localError(n[1].info, errOrdinalTypeExpected)
|
localError(n[1].info, errOrdinalTypeExpected)
|
||||||
result = makeRangeWithStaticExpr(c, e)
|
result = makeRangeWithStaticExpr(c, e)
|
||||||
result.flags.incl tfUnresolved
|
if c.inGenericContext >0: result.flags.incl tfUnresolved
|
||||||
elif e.kind in nkCallKinds and hasGenericArguments(e):
|
elif e.kind in nkCallKinds and hasGenericArguments(e):
|
||||||
if not isOrdinalType(e.typ):
|
if not isOrdinalType(e.typ):
|
||||||
localError(n[1].info, errOrdinalTypeExpected)
|
localError(n[1].info, errOrdinalTypeExpected)
|
||||||
|
|
@ -782,10 +781,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
of tyGenericBody:
|
of tyGenericBody:
|
||||||
result = newTypeS(tyGenericInvokation, c)
|
result = newTypeS(tyGenericInvokation, c)
|
||||||
result.rawAddSon(paramType)
|
result.rawAddSon(paramType)
|
||||||
|
|
||||||
for i in 0 .. paramType.sonsLen - 2:
|
for i in 0 .. paramType.sonsLen - 2:
|
||||||
result.rawAddSon newTypeS(tyAnything, c)
|
let dummyType = if paramType.sons[i].kind == tyStatic: tyUnknown
|
||||||
# result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true))
|
else: tyAnything
|
||||||
|
result.rawAddSon newTypeS(dummyType, c)
|
||||||
|
|
||||||
if paramType.lastSon.kind == tyUserTypeClass:
|
if paramType.lastSon.kind == tyUserTypeClass:
|
||||||
result.kind = tyUserTypeClassInst
|
result.kind = tyUserTypeClassInst
|
||||||
result.rawAddSon paramType.lastSon
|
result.rawAddSon paramType.lastSon
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,9 @@ type
|
||||||
bindings*: TIdTable # maps types to types
|
bindings*: TIdTable # maps types to types
|
||||||
baseTypeMatch: bool # needed for conversions from T to openarray[T]
|
baseTypeMatch: bool # needed for conversions from T to openarray[T]
|
||||||
# for example
|
# for example
|
||||||
proxyMatch*: bool # to prevent instantiations
|
fauxMatch*: TTypeKind # the match was successful only due to the use
|
||||||
|
# of error or wildcard (unknown) types.
|
||||||
|
# this is used to prevent instantiations.
|
||||||
genericConverter*: bool # true if a generic converter needs to
|
genericConverter*: bool # true if a generic converter needs to
|
||||||
# be instantiated
|
# be instantiated
|
||||||
coerceDistincts*: bool # this is an explicit coercion that can strip away
|
coerceDistincts*: bool # this is an explicit coercion that can strip away
|
||||||
|
|
@ -66,6 +68,8 @@ const
|
||||||
|
|
||||||
proc markUsed*(info: TLineInfo, s: PSym)
|
proc markUsed*(info: TLineInfo, s: PSym)
|
||||||
|
|
||||||
|
template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
|
||||||
|
|
||||||
proc initCandidateAux(ctx: PContext,
|
proc initCandidateAux(ctx: PContext,
|
||||||
c: var TCandidate, callee: PType) {.inline.} =
|
c: var TCandidate, callee: PType) {.inline.} =
|
||||||
c.c = ctx
|
c.c = ctx
|
||||||
|
|
@ -109,9 +113,12 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
|
||||||
for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
|
for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
|
||||||
var formalTypeParam = typeParams.sons[i-1].typ
|
var formalTypeParam = typeParams.sons[i-1].typ
|
||||||
var bound = binding[i].typ
|
var bound = binding[i].typ
|
||||||
if bound != nil and formalTypeParam.kind != tyTypeDesc:
|
internalAssert bound != nil
|
||||||
|
if formalTypeParam.kind == tyTypeDesc:
|
||||||
|
if bound.kind != tyTypeDesc:
|
||||||
|
bound = makeTypeDesc(ctx, bound)
|
||||||
|
else:
|
||||||
bound = bound.skipTypes({tyTypeDesc})
|
bound = bound.skipTypes({tyTypeDesc})
|
||||||
assert bound != nil
|
|
||||||
put(c.bindings, formalTypeParam, bound)
|
put(c.bindings, formalTypeParam, bound)
|
||||||
|
|
||||||
proc newCandidate*(ctx: PContext, callee: PSym,
|
proc newCandidate*(ctx: PContext, callee: PSym,
|
||||||
|
|
@ -462,9 +469,23 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
|
||||||
var
|
var
|
||||||
typeParamName = ff.base.sons[i-1].sym.name
|
typeParamName = ff.base.sons[i-1].sym.name
|
||||||
typ = ff.sons[i]
|
typ = ff.sons[i]
|
||||||
param = newSym(skType, typeParamName, body.sym, body.sym.info)
|
param: PSym
|
||||||
|
|
||||||
param.typ = makeTypeDesc(c, typ)
|
template paramSym(kind): expr =
|
||||||
|
newSym(kind, typeParamName, body.sym, body.sym.info)
|
||||||
|
|
||||||
|
case typ.kind
|
||||||
|
of tyStatic:
|
||||||
|
param = paramSym skConst
|
||||||
|
param.typ = typ.base
|
||||||
|
param.ast = typ.n
|
||||||
|
of tyUnknown:
|
||||||
|
param = paramSym skVar
|
||||||
|
param.typ = typ
|
||||||
|
else:
|
||||||
|
param = paramSym skType
|
||||||
|
param.typ = makeTypeDesc(c, typ)
|
||||||
|
|
||||||
addDecl(c, param)
|
addDecl(c, param)
|
||||||
|
|
||||||
for param in body.n[0]:
|
for param in body.n[0]:
|
||||||
|
|
@ -626,6 +647,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype
|
elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype
|
||||||
of tyRange:
|
of tyRange:
|
||||||
if a.kind == f.kind:
|
if a.kind == f.kind:
|
||||||
|
if f.base.kind == tyNone: return isGeneric
|
||||||
result = typeRel(c, base(f), base(a))
|
result = typeRel(c, base(f), base(a))
|
||||||
# bugfix: accept integer conversions here
|
# bugfix: accept integer conversions here
|
||||||
#if result < isGeneric: result = isNone
|
#if result < isGeneric: result = isNone
|
||||||
|
|
@ -672,22 +694,27 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
else:
|
else:
|
||||||
fRange = prev
|
fRange = prev
|
||||||
result = typeRel(c, f.sons[1], a.sons[1])
|
result = typeRel(c, f.sons[1], a.sons[1])
|
||||||
if result < isGeneric:
|
if result < isGeneric: return isNone
|
||||||
result = isNone
|
if rangeHasStaticIf(fRange):
|
||||||
elif tfUnresolved in fRange.flags and
|
if tfUnresolved in fRange.flags:
|
||||||
rangeHasStaticIf(fRange):
|
# This is a range from an array instantiated with a generic
|
||||||
# This is a range from an array instantiated with a generic
|
# static param. We must extract the static param here and bind
|
||||||
# static param. We must extract the static param here and bind
|
# it to the size of the currently supplied array.
|
||||||
# it to the size of the currently supplied array.
|
var
|
||||||
var
|
rangeStaticT = fRange.getStaticTypeFromRange
|
||||||
rangeStaticT = fRange.getStaticTypeFromRange
|
replacementT = newTypeWithSons(c.c, tyStatic, @[tyInt.getSysType])
|
||||||
replacementT = newTypeWithSons(c.c, tyStatic, @[tyInt.getSysType])
|
inputUpperBound = a.sons[0].n[1].intVal
|
||||||
inputUpperBound = a.sons[0].n[1].intVal
|
# we must correct for the off-by-one discrepancy between
|
||||||
# we must correct for the off-by-one discrepancy between
|
# ranges and static params:
|
||||||
# ranges and static params:
|
replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1)
|
||||||
replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1)
|
put(c.bindings, rangeStaticT, replacementT)
|
||||||
put(c.bindings, rangeStaticT, replacementT)
|
return isGeneric
|
||||||
result = isGeneric
|
|
||||||
|
let len = tryResolvingStaticExpr(c, fRange.n[1])
|
||||||
|
if len.kind == nkIntLit and len.intVal+1 == lengthOrd(a):
|
||||||
|
return # if we get this far, the result is already good
|
||||||
|
else:
|
||||||
|
return isNone
|
||||||
elif lengthOrd(fRange) != lengthOrd(a):
|
elif lengthOrd(fRange) != lengthOrd(a):
|
||||||
result = isNone
|
result = isNone
|
||||||
else: discard
|
else: discard
|
||||||
|
|
@ -945,7 +972,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
else:
|
else:
|
||||||
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.base)
|
result = typeRel(c, f.base, a.skipTypes({tyGenericParam, tyTypeDesc}))
|
||||||
else:
|
else:
|
||||||
result = isNone
|
result = isNone
|
||||||
else:
|
else:
|
||||||
|
|
@ -980,7 +1007,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
if aOrig.kind == tyStatic:
|
if aOrig.kind == tyStatic:
|
||||||
result = typeRel(c, f.lastSon, a)
|
result = typeRel(c, f.lastSon, a)
|
||||||
if result != isNone and f.n != nil:
|
if result != isNone and f.n != nil:
|
||||||
if not exprStructuralEquivalent(f.n, a.n):
|
if not exprStructuralEquivalent(f.n, aOrig.n):
|
||||||
result = isNone
|
result = isNone
|
||||||
if result != isNone: put(c.bindings, f, aOrig)
|
if result != isNone: put(c.bindings, f, aOrig)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1045,10 +1072,10 @@ proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation =
|
||||||
initCandidate(c, m, f)
|
initCandidate(c, m, f)
|
||||||
result = typeRel(m, f, a)
|
result = typeRel(m, f, a)
|
||||||
|
|
||||||
proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
|
proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
|
||||||
f: PType): PType =
|
f: PType): PType =
|
||||||
result = PType(idTableGet(m.bindings, f))
|
result = PType(idTableGet(m.bindings, f))
|
||||||
if result == nil:
|
if result == nil:
|
||||||
result = generateTypeInstance(c, m.bindings, arg, f)
|
result = generateTypeInstance(c, m.bindings, arg, f)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
internalError(arg.info, "getInstantiatedType")
|
internalError(arg.info, "getInstantiatedType")
|
||||||
|
|
@ -1058,7 +1085,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
|
||||||
c: PContext): PNode =
|
c: PContext): PNode =
|
||||||
result = newNodeI(kind, arg.info)
|
result = newNodeI(kind, arg.info)
|
||||||
if containsGenericType(f):
|
if containsGenericType(f):
|
||||||
if not m.proxyMatch:
|
if not m.hasFauxMatch:
|
||||||
result.typ = getInstantiatedType(c, arg, m, f)
|
result.typ = getInstantiatedType(c, arg, m, f)
|
||||||
else:
|
else:
|
||||||
result.typ = errorType(c)
|
result.typ = errorType(c)
|
||||||
|
|
@ -1130,7 +1157,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
arg = argSemantized
|
arg = argSemantized
|
||||||
argType = argType
|
argType = argType
|
||||||
c = m.c
|
c = m.c
|
||||||
|
|
||||||
if tfHasStatic in fMaybeStatic.flags:
|
if tfHasStatic in fMaybeStatic.flags:
|
||||||
# XXX: When implicit statics are the default
|
# XXX: When implicit statics are the default
|
||||||
# this will be done earlier - we just have to
|
# this will be done earlier - we just have to
|
||||||
|
|
@ -1144,7 +1171,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
return argSemantized
|
return argSemantized
|
||||||
|
|
||||||
if argType.kind == tyStatic:
|
if argType.kind == tyStatic:
|
||||||
if m.callee.kind == tyGenericBody:
|
if m.callee.kind == tyGenericBody and tfGenericTypeParam notin argType.flags:
|
||||||
result = newNodeI(nkType, argOrig.info)
|
result = newNodeI(nkType, argOrig.info)
|
||||||
result.typ = makeTypeFromExpr(c, arg)
|
result.typ = makeTypeFromExpr(c, arg)
|
||||||
return
|
return
|
||||||
|
|
@ -1237,9 +1264,9 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
||||||
of isNone:
|
of isNone:
|
||||||
# do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
|
# do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
|
||||||
if a.kind == tyProxy:
|
if a.kind in {tyProxy, tyUnknown}:
|
||||||
inc(m.genericMatches)
|
inc(m.genericMatches)
|
||||||
m.proxyMatch = true
|
m.fauxMatch = a.kind
|
||||||
return copyTree(arg)
|
return copyTree(arg)
|
||||||
result = userConvMatch(c, m, f, a, arg)
|
result = userConvMatch(c, m, f, a, arg)
|
||||||
# check for a base type match, which supports varargs[T] without []
|
# check for a base type match, which supports varargs[T] without []
|
||||||
|
|
|
||||||
|
|
@ -1070,7 +1070,7 @@ Operation Comment
|
||||||
``dec(x, n)`` decrements `x` by `n`; `n` is an integer
|
``dec(x, n)`` decrements `x` by `n`; `n` is an integer
|
||||||
``succ(x)`` returns the successor of `x`
|
``succ(x)`` returns the successor of `x`
|
||||||
``succ(x, n)`` returns the `n`'th successor of `x`
|
``succ(x, n)`` returns the `n`'th successor of `x`
|
||||||
``prec(x)`` returns the predecessor of `x`
|
``pred(x)`` returns the predecessor of `x`
|
||||||
``pred(x, n)`` returns the `n`'th predecessor of `x`
|
``pred(x, n)`` returns the `n`'th predecessor of `x`
|
||||||
----------------- --------------------------------------------------------
|
----------------- --------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -1323,7 +1323,7 @@ define operators which accept TSlice objects to define ranges.
|
||||||
a = "Nim is a progamming language"
|
a = "Nim is a progamming language"
|
||||||
b = "Slices are useless."
|
b = "Slices are useless."
|
||||||
|
|
||||||
echo a[10..15] # --> 'a prog'
|
echo a[7..12] # --> 'a prog'
|
||||||
b[11.. -2] = "useful"
|
b[11.. -2] = "useful"
|
||||||
echo b # --> 'Slices are useful.'
|
echo b # --> 'Slices are useful.'
|
||||||
|
|
||||||
|
|
|
||||||
16
tests/generics/t1050.nim
Normal file
16
tests/generics/t1050.nim
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
discard """
|
||||||
|
msg: "int"
|
||||||
|
output: "4"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import typetraits
|
||||||
|
|
||||||
|
type ArrayType[T] = distinct T
|
||||||
|
|
||||||
|
proc arrayItem(a: ArrayType): auto =
|
||||||
|
static: echo(name(type(a).T))
|
||||||
|
result = (type(a).T)(4)
|
||||||
|
|
||||||
|
var arr: ArrayType[int]
|
||||||
|
echo arrayItem(arr)
|
||||||
|
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
discard """
|
discard """
|
||||||
msg: "static 10\ndynamic\nstatic 20\n"
|
msg: "static 10\ndynamic\nstatic 20\n"
|
||||||
output: "s\nd\nd\ns"
|
output: "s\nd\nd\ns"
|
||||||
disabled: "true"
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
semistatic[T] =
|
||||||
|
static[T] or T
|
||||||
|
|
||||||
|
template isStatic*(x): expr =
|
||||||
|
compiles(static(x))
|
||||||
|
|
||||||
proc foo(x: semistatic[int]) =
|
proc foo(x: semistatic[int]) =
|
||||||
when isStatic(x):
|
when isStatic(x):
|
||||||
static: echo "static ", x
|
static: echo "static ", x
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
file: "tstaticparams.nim"
|
file: "tstaticparams.nim"
|
||||||
output: "abracadabra\ntest\n3\n15\n4\n2"
|
output: "abracadabra\ntest\n3\n15\n4\n2\nfloat\n3\nfloat\nyin\nyang"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -56,3 +56,66 @@ type TTestSub[N: static[int]] = TTest[1, N]
|
||||||
|
|
||||||
var z: TTestSub[2]
|
var z: TTestSub[2]
|
||||||
echo z.high
|
echo z.high
|
||||||
|
|
||||||
|
# issue 1049
|
||||||
|
proc matrix_1*[M, N, T](mat: Matrix[M,N,T], a: array[N, int]) = discard
|
||||||
|
proc matrix_2*[M, N, T](mat: Matrix[M,N,T], a: array[N+1, int]) = discard
|
||||||
|
|
||||||
|
proc matrix_3*[M, N: static[int]; T](mat: Matrix[M,N,T], a: array[N, int]) = discard
|
||||||
|
proc matrix_4*[M, N: static[int]; T](mat: Matrix[M,N,T], a: array[N+1, int]) = discard
|
||||||
|
|
||||||
|
var
|
||||||
|
tmat: Matrix[4,4,int]
|
||||||
|
ar1: array[4, int]
|
||||||
|
ar2: array[5, int]
|
||||||
|
|
||||||
|
matrix_1(tmat, ar1)
|
||||||
|
matrix_2(tmat, ar2)
|
||||||
|
matrix_3(tmat, ar1)
|
||||||
|
matrix_4(tmat, ar2)
|
||||||
|
|
||||||
|
template reject(x): stmt =
|
||||||
|
static: assert(not compiles(x))
|
||||||
|
|
||||||
|
# test with arrays of wrong size
|
||||||
|
reject matrix_1(tmat, ar2)
|
||||||
|
reject matrix_2(tmat, ar1)
|
||||||
|
reject matrix_3(tmat, ar2)
|
||||||
|
reject matrix_4(tmat, ar1)
|
||||||
|
|
||||||
|
# bug 1820
|
||||||
|
|
||||||
|
type
|
||||||
|
T1820_1[T; Y: static[int]] = object
|
||||||
|
bar: T
|
||||||
|
|
||||||
|
proc intOrFloat*[Y](f: T1820_1[int, Y]) = echo "int"
|
||||||
|
proc intOrFloat*[Y](f: T1820_1[float, Y]) = echo "float"
|
||||||
|
proc threeOrFour*[T](f: T1820_1[T, 3]) = echo "3"
|
||||||
|
proc threeOrFour*[T](f: T1820_1[T, 4]) = echo "4"
|
||||||
|
|
||||||
|
var foo_1: T1820_1[float, 3]
|
||||||
|
|
||||||
|
foo_1.intOrFloat
|
||||||
|
foo_1.threeOrFour
|
||||||
|
|
||||||
|
type
|
||||||
|
YinAndYang = enum
|
||||||
|
Yin,
|
||||||
|
Yang
|
||||||
|
|
||||||
|
T1820_2[T; Y: static[YinAndYang]] = object
|
||||||
|
bar: T
|
||||||
|
|
||||||
|
proc intOrFloat*[Y](f: T1820_2[int, Y]) = echo "int"
|
||||||
|
proc intOrFloat*[Y](f: T1820_2[float, Y]) = echo "float"
|
||||||
|
proc yinOrYang*[T](f: T1820_2[T, YinAndYang.Yin]) = echo "yin"
|
||||||
|
proc yinOrYang*[T](f: T1820_2[T, Yang]) = echo "yang"
|
||||||
|
|
||||||
|
var foo_2: T1820_2[float, Yin]
|
||||||
|
var foo_3: T1820_2[float, YinAndYang.Yang]
|
||||||
|
|
||||||
|
foo_2.intOrFloat
|
||||||
|
foo_2.yinOrYang
|
||||||
|
foo_3.yinOrYang
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,13 @@
|
||||||
discard """
|
discard """
|
||||||
output: "Sortable\nSortable\nContainer"
|
output: '''Sortable
|
||||||
|
Sortable
|
||||||
|
Container
|
||||||
|
true
|
||||||
|
true
|
||||||
|
false
|
||||||
|
false
|
||||||
|
false
|
||||||
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import typetraits
|
import typetraits
|
||||||
|
|
@ -41,3 +49,20 @@ proc y(x: TObj): int = 10
|
||||||
proc testFoo(x: TFoo) = discard
|
proc testFoo(x: TFoo) = discard
|
||||||
testFoo(TObj(x: 10))
|
testFoo(TObj(x: 10))
|
||||||
|
|
||||||
|
type
|
||||||
|
Matrix[Rows, Cols: static[int]; T] = generic M
|
||||||
|
M.M == Rows
|
||||||
|
M.N == Cols
|
||||||
|
M.T is T
|
||||||
|
|
||||||
|
MyMatrix[M, N: static[int]; T] = object
|
||||||
|
data: array[M*N, T]
|
||||||
|
|
||||||
|
var x: MyMatrix[3, 3, int]
|
||||||
|
|
||||||
|
echo x is Matrix
|
||||||
|
echo x is Matrix[3, 3, int]
|
||||||
|
echo x is Matrix[3, 3, float]
|
||||||
|
echo x is Matrix[4, 3, int]
|
||||||
|
echo x is Matrix[3, 4, int]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,67 +1,67 @@
|
||||||
# Test various aspects
|
# Test various aspects
|
||||||
|
|
||||||
# bug #572
|
# bug #572
|
||||||
var a=12345678901'u64
|
var a=12345678901'u64
|
||||||
|
|
||||||
var x = (x: 42, y: (a: 8, z: 10))
|
var x = (x: 42, y: (a: 8, z: 10))
|
||||||
echo x.y
|
echo x.y
|
||||||
|
|
||||||
import
|
import
|
||||||
mvarious
|
mvarious
|
||||||
|
|
||||||
type
|
type
|
||||||
PA = ref TA
|
PA = ref TA
|
||||||
PB = ref TB
|
PB = ref TB
|
||||||
|
|
||||||
TB = object
|
TB = object
|
||||||
a: PA
|
a: PA
|
||||||
|
|
||||||
TA = object
|
TA = object
|
||||||
b: TB
|
b: TB
|
||||||
x: int
|
x: int
|
||||||
|
|
||||||
proc getPA(): PA =
|
proc getPA(): PA =
|
||||||
var
|
var
|
||||||
b: bool
|
b: bool
|
||||||
b = not false
|
b = not false
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
# bug #501
|
# bug #501
|
||||||
proc f(): int = 54
|
proc f(): int = 54
|
||||||
|
|
||||||
var
|
var
|
||||||
global: int
|
global: int
|
||||||
|
|
||||||
var
|
var
|
||||||
s: string
|
s: string
|
||||||
i: int
|
i: int
|
||||||
r: TA
|
r: TA
|
||||||
|
|
||||||
r.b.a.x = 0
|
r.b.a.x = 0
|
||||||
global = global + 1
|
global = global + 1
|
||||||
exportme()
|
exportme()
|
||||||
write(stdout, "Hallo wie heißt du? ")
|
write(stdout, "Hallo wie heißt du? ")
|
||||||
write(stdout, getPA().x)
|
write(stdout, getPA().x)
|
||||||
s = readLine(stdin)
|
s = readLine(stdin)
|
||||||
i = 0
|
i = 0
|
||||||
while i < s.len:
|
while i < s.len:
|
||||||
if s[i] == 'c': write(stdout, "'c' in deinem Namen gefunden\n")
|
if s[i] == 'c': write(stdout, "'c' in deinem Namen gefunden\n")
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
|
||||||
write(stdout, "Du heißt " & s)
|
write(stdout, "Du heißt " & s)
|
||||||
|
|
||||||
# bug #544
|
# bug #544
|
||||||
when false:
|
|
||||||
# yay, fails again
|
# yay, fails again
|
||||||
type Bar [T; I:range] = array[I, T]
|
type Bar [T; I:range] = array[I, T]
|
||||||
proc foo*[T; I:range](a, b: Bar[T, I]): Bar[T, I] =
|
proc foo*[T; I:range](a, b: Bar[T, I]): Bar[T, I] =
|
||||||
when len(a) != 3:
|
when len(a) != 3:
|
||||||
# Error: constant expression expected
|
# Error: constant expression expected
|
||||||
{.fatal:"Dimensions have to be 3".}
|
{.fatal:"Dimensions have to be 3".}
|
||||||
#...
|
#...
|
||||||
block:
|
block:
|
||||||
var a, b: Bar[int, 0..2]
|
var a, b: Bar[int, range[0..2]]
|
||||||
discard foo(a, b)
|
discard foo(a, b)
|
||||||
|
|
||||||
# bug #1788
|
# bug #1788
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue