mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-20 07:51:32 +00:00
first phase of tyGenericParam reforms needed for static params
This commit is contained in:
@@ -382,6 +382,10 @@ type
|
||||
# sons[0]: type of containing object or tuple
|
||||
# sons[1]: field type
|
||||
# .n: nkDotExpr storing the field name
|
||||
|
||||
static:
|
||||
# remind us when TTypeKind stops to fit in a single 64-bit word
|
||||
assert TTypeKind.high.ord <= 63
|
||||
|
||||
const
|
||||
tyPureObject* = tyTuple
|
||||
@@ -448,6 +452,10 @@ type
|
||||
tfHasStatic
|
||||
tfGenericTypeParam
|
||||
tfImplicitTypeParam
|
||||
tfWildcard # consider a proc like foo[T, I](x: Type[T, I])
|
||||
# T and I here can bind to both typedesc and static types
|
||||
# before this is determined, we'll consider them to be a
|
||||
# wildcard type.
|
||||
|
||||
TTypeFlags* = set[TTypeFlag]
|
||||
|
||||
@@ -693,7 +701,7 @@ type
|
||||
TSym* {.acyclic.} = object of TIdObj
|
||||
# proc and type instantiations are cached in the generic symbol
|
||||
case kind*: TSymKind
|
||||
of skType:
|
||||
of skType, skGenericParam:
|
||||
typeInstCache*: seq[PType]
|
||||
typScope*: PScope
|
||||
of routineKinds:
|
||||
@@ -1495,6 +1503,9 @@ proc hasPattern*(s: PSym): bool {.inline.} =
|
||||
iterator items*(n: PNode): PNode =
|
||||
for i in 0.. <n.len: yield n.sons[i]
|
||||
|
||||
iterator pairs*(n: PNode): tuple[i: int, n: PNode] =
|
||||
for i in 0.. <n.len: yield (i, n.sons[i])
|
||||
|
||||
proc isAtom*(n: PNode): bool {.inline.} =
|
||||
result = n.kind >= nkNone and n.kind <= nkNilLit
|
||||
|
||||
|
||||
@@ -117,8 +117,8 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
elif s.ast != nil:
|
||||
result = semExpr(c, s.ast)
|
||||
else:
|
||||
internalError(n.info, "no default for")
|
||||
result = emptyNode
|
||||
n.typ = s.typ
|
||||
return n
|
||||
of skType:
|
||||
markUsed(n, s)
|
||||
result = newSymNode(s, n.info)
|
||||
|
||||
@@ -15,8 +15,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
|
||||
if n.kind != nkGenericParams:
|
||||
internalError(n.info, "instantiateGenericParamList; no generic params")
|
||||
newSeq(entry.concreteTypes, n.len)
|
||||
for i in countup(0, n.len - 1):
|
||||
var a = n.sons[i]
|
||||
for i, a in n.pairs:
|
||||
if a.kind != nkSym:
|
||||
internalError(a.info, "instantiateGenericParamList; no symbol")
|
||||
var q = a.sym
|
||||
@@ -149,7 +148,6 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
info: TLineInfo): PSym =
|
||||
# no need to instantiate generic templates/macros:
|
||||
if fn.kind in {skTemplate, skMacro}: return fn
|
||||
|
||||
# generates an instantiated proc
|
||||
if c.instCounter > 1000: internalError(fn.ast.info, "nesting too deep")
|
||||
inc(c.instCounter)
|
||||
@@ -183,9 +181,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
pragma(c, result, n.sons[pragmasPos], allRoutinePragmas)
|
||||
if isNil(n.sons[bodyPos]):
|
||||
n.sons[bodyPos] = copyTree(fn.getBody)
|
||||
if fn.kind != skTemplate:
|
||||
instantiateBody(c, n, result)
|
||||
sideEffectsCheck(c, result)
|
||||
instantiateBody(c, n, result)
|
||||
sideEffectsCheck(c, result)
|
||||
paramsTypeCheck(c, result.typ)
|
||||
else:
|
||||
result = oldPrc
|
||||
|
||||
@@ -203,6 +203,14 @@ proc nMinusOne(n: PNode): PNode =
|
||||
newSymNode(getSysMagic("<", mUnaryLt)),
|
||||
n])
|
||||
|
||||
proc makeRangeWithStaticExpr(c: PContext, n: PNode): PType =
|
||||
let intType = getSysType tyInt
|
||||
result = newTypeS(tyRange, c)
|
||||
result.sons = @[intType]
|
||||
result.n = newNode(nkRange, n.info, @[
|
||||
newIntTypeNode(nkIntLit, 0, intType),
|
||||
makeStaticExpr(c, n.nMinusOne)])
|
||||
|
||||
proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
var indx, base: PType
|
||||
result = newOrPrevType(tyArray, prev, c)
|
||||
@@ -220,7 +228,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
internalAssert c.inGenericContext > 0
|
||||
if not isOrdinalType(e.typ.lastSon):
|
||||
localError(n[1].info, errOrdinalTypeExpected)
|
||||
indx = e.typ
|
||||
indx = makeRangeWithStaticExpr(c, e)
|
||||
elif e.kind in nkCallKinds and hasGenericArguments(e):
|
||||
if not isOrdinalType(e.typ):
|
||||
localError(n[1].info, errOrdinalTypeExpected)
|
||||
@@ -229,12 +237,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
# We are going to construct a range type that will be
|
||||
# properly filled-out in semtypinst (see how tyStaticExpr
|
||||
# is handled there).
|
||||
let intType = getSysType(tyInt)
|
||||
indx = newTypeS(tyRange, c)
|
||||
indx.sons = @[intType]
|
||||
indx.n = newNode(nkRange, n.info, @[
|
||||
newIntTypeNode(nkIntLit, 0, intType),
|
||||
makeStaticExpr(c, e.nMinusOne)])
|
||||
indx = makeRangeWithStaticExpr(c, e)
|
||||
else:
|
||||
indx = e.typ.skipTypes({tyTypeDesc})
|
||||
addSonSkipIntLit(result, indx)
|
||||
@@ -283,6 +286,18 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
result = result.typ.sym.copySym
|
||||
result.typ = copyType(result.typ, result.typ.owner, true)
|
||||
result.typ.flags.incl tfUnresolved
|
||||
|
||||
if result.kind == skGenericParam:
|
||||
if result.typ.kind == tyGenericParam and result.typ.len == 0 and
|
||||
tfWildcard in result.typ.flags:
|
||||
# collapse the wild-card param to a type
|
||||
result.kind = skType
|
||||
result.typ.flags.excl tfWildcard
|
||||
return
|
||||
else:
|
||||
localError(n.info, errTypeExpected)
|
||||
return errorSym(c, n)
|
||||
|
||||
if result.kind != skType:
|
||||
# this implements the wanted ``var v: V, x: V`` feature ...
|
||||
var ov: TOverloadIter
|
||||
@@ -737,7 +752,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
result.kind = tyUserTypeClassInst
|
||||
result.rawAddSon paramType.lastSon
|
||||
return addImplicitGeneric(result)
|
||||
|
||||
|
||||
result = instGenericContainer(c, paramType.sym.info, result,
|
||||
allowMetaTypes = true)
|
||||
result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result])
|
||||
@@ -787,11 +802,9 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
result = addImplicitGeneric(newTypeS(tyAnything, c))
|
||||
|
||||
of tyGenericParam:
|
||||
if tfGenericTypeParam in paramType.flags and false:
|
||||
if paramType.sonsLen > 0:
|
||||
result = liftingWalk(paramType.lastSon)
|
||||
else:
|
||||
result = addImplicitGeneric(newTypeS(tyAnything, c))
|
||||
if tfWildcard in paramType.flags:
|
||||
paramType.flags.excl tfWildcard
|
||||
paramType.sym.kind = skType
|
||||
|
||||
else: discard
|
||||
|
||||
@@ -804,8 +817,8 @@ proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType =
|
||||
else:
|
||||
result = semTypeNode(c, n, nil)
|
||||
|
||||
proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
prev: PType, kind: TSymKind): PType =
|
||||
proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
prev: PType, kind: TSymKind): PType =
|
||||
var
|
||||
res: PNode
|
||||
cl: TIntSet
|
||||
@@ -894,6 +907,12 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
result.sons[0] = r
|
||||
res.typ = r
|
||||
|
||||
if genericParams != nil:
|
||||
for n in genericParams:
|
||||
if tfUnresolved in n.sym.typ.flags:
|
||||
n.sym.kind = skType
|
||||
n.sym.typ.flags.excl tfWildcard
|
||||
|
||||
proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
|
||||
checkMinSonsLen(n, 1)
|
||||
var length = sonsLen(n)
|
||||
@@ -944,7 +963,6 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
|
||||
localError(n.info, errNoGenericParamsAllowedForX, s.name.s)
|
||||
return newOrPrevType(tyError, prev, c)
|
||||
else:
|
||||
|
||||
var m = newCandidate(c, s, n)
|
||||
matches(c, n, copyTree(n), m)
|
||||
|
||||
@@ -1262,6 +1280,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
|
||||
if typ == nil:
|
||||
typ = newTypeS(tyGenericParam, c)
|
||||
if father == nil: typ.flags.incl tfWildcard
|
||||
|
||||
typ.flags.incl tfGenericTypeParam
|
||||
|
||||
@@ -1272,8 +1291,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
# type for each generic param. the index
|
||||
# of the parameter will be stored in the
|
||||
# attached symbol.
|
||||
var s = case finalType.kind
|
||||
of tyStatic:
|
||||
var s = if finalType.kind == tyStatic or tfWildcard in typ.flags:
|
||||
newSymG(skGenericParam, a.sons[j], c).linkTo(finalType)
|
||||
else:
|
||||
newSymG(skType, a.sons[j], c).linkTo(finalType)
|
||||
|
||||
@@ -394,21 +394,11 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||
propagateToOwner(result, result.sons[i])
|
||||
|
||||
result.n = replaceTypeVarsN(cl, result.n)
|
||||
|
||||
# XXX: This is not really needed?
|
||||
# if result.kind in GenericTypes:
|
||||
# localError(cl.info, errCannotInstantiateX, typeToString(t, preferName))
|
||||
|
||||
|
||||
case result.kind
|
||||
of tyArray:
|
||||
let idx = result.sons[0]
|
||||
if idx.kind == tyStatic:
|
||||
if idx.n == nil:
|
||||
let lookup = lookupTypeVar(cl, idx)
|
||||
internalAssert lookup != nil
|
||||
idx.n = lookup.n
|
||||
|
||||
result.sons[0] = makeRangeType(cl.c, 0, idx.n.intVal - 1, idx.n.info)
|
||||
internalAssert idx.kind != tyStatic
|
||||
|
||||
of tyObject, tyTuple:
|
||||
propagateFieldFlags(result, result.n)
|
||||
|
||||
@@ -620,8 +620,10 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||
else:
|
||||
fRange = prev
|
||||
result = typeRel(c, f.sons[1], a.sons[1])
|
||||
if result < isGeneric: result = isNone
|
||||
elif lengthOrd(fRange) != lengthOrd(a): result = isNone
|
||||
if result < isGeneric:
|
||||
result = isNone
|
||||
elif lengthOrd(fRange) != lengthOrd(a):
|
||||
result = isNone
|
||||
else: discard
|
||||
of tyOpenArray, tyVarargs:
|
||||
case a.kind
|
||||
@@ -867,7 +869,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||
# any value" and what we need is "match any type", which can be encoded
|
||||
# by a tyTypeDesc params. Unfortunately, this requires more substantial
|
||||
# changes in semtypinst and elsewhere.
|
||||
if a.kind == tyTypeDesc:
|
||||
if a.kind == tyTypeDesc or tfWildcard in a.flags:
|
||||
if f.sonsLen == 0:
|
||||
result = isGeneric
|
||||
else:
|
||||
@@ -883,11 +885,16 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||
result = isGeneric
|
||||
|
||||
if result == isGeneric:
|
||||
var concrete = concreteType(c, a)
|
||||
if concrete == nil:
|
||||
result = isNone
|
||||
var concrete = a
|
||||
if tfWildcard in a.flags:
|
||||
a.sym.kind = skType
|
||||
a.flags.excl tfWildcard
|
||||
else:
|
||||
if doBind: put(c.bindings, f, concrete)
|
||||
concrete = concreteType(c, a)
|
||||
if concrete == nil:
|
||||
return isNone
|
||||
if doBind:
|
||||
put(c.bindings, f, concrete)
|
||||
elif a.kind == tyEmpty:
|
||||
result = isGeneric
|
||||
elif x.kind == tyGenericParam:
|
||||
@@ -1025,11 +1032,20 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||
arg = argSemantized
|
||||
argType = argType
|
||||
c = m.c
|
||||
|
||||
|
||||
if tfHasStatic in fMaybeStatic.flags:
|
||||
# XXX: When implicit statics are the default
|
||||
# this will be done earlier - we just have to
|
||||
# make sure that static types enter here
|
||||
|
||||
# XXX: weaken tyGenericParam and call it tyGenericPlaceholder
|
||||
# and finally start using tyTypedesc for generic types properly.
|
||||
if argType.kind == tyGenericParam and tfWildcard in argType.flags:
|
||||
argType.assignType(f)
|
||||
argType.flags.incl tfUnresolved
|
||||
# put(m.bindings, f, argType)
|
||||
return argSemantized
|
||||
|
||||
var evaluated = c.semTryConstExpr(c, arg)
|
||||
if evaluated != nil:
|
||||
arg.typ = newTypeS(tyStatic, c)
|
||||
|
||||
Reference in New Issue
Block a user