first phase of tyGenericParam reforms needed for static params
This commit is contained in:
parent
4d2c948281
commit
37b199d34a
6 changed files with 79 additions and 47 deletions
|
|
@ -383,6 +383,10 @@ type
|
||||||
# sons[1]: field type
|
# sons[1]: field type
|
||||||
# .n: nkDotExpr storing the field name
|
# .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
|
const
|
||||||
tyPureObject* = tyTuple
|
tyPureObject* = tyTuple
|
||||||
GcTypeKinds* = {tyRef, tySequence, tyString}
|
GcTypeKinds* = {tyRef, tySequence, tyString}
|
||||||
|
|
@ -448,6 +452,10 @@ type
|
||||||
tfHasStatic
|
tfHasStatic
|
||||||
tfGenericTypeParam
|
tfGenericTypeParam
|
||||||
tfImplicitTypeParam
|
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]
|
TTypeFlags* = set[TTypeFlag]
|
||||||
|
|
||||||
|
|
@ -693,7 +701,7 @@ type
|
||||||
TSym* {.acyclic.} = object of TIdObj
|
TSym* {.acyclic.} = object of TIdObj
|
||||||
# proc and type instantiations are cached in the generic symbol
|
# proc and type instantiations are cached in the generic symbol
|
||||||
case kind*: TSymKind
|
case kind*: TSymKind
|
||||||
of skType:
|
of skType, skGenericParam:
|
||||||
typeInstCache*: seq[PType]
|
typeInstCache*: seq[PType]
|
||||||
typScope*: PScope
|
typScope*: PScope
|
||||||
of routineKinds:
|
of routineKinds:
|
||||||
|
|
@ -1495,6 +1503,9 @@ proc hasPattern*(s: PSym): bool {.inline.} =
|
||||||
iterator items*(n: PNode): PNode =
|
iterator items*(n: PNode): PNode =
|
||||||
for i in 0.. <n.len: yield n.sons[i]
|
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.} =
|
proc isAtom*(n: PNode): bool {.inline.} =
|
||||||
result = n.kind >= nkNone and n.kind <= nkNilLit
|
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:
|
elif s.ast != nil:
|
||||||
result = semExpr(c, s.ast)
|
result = semExpr(c, s.ast)
|
||||||
else:
|
else:
|
||||||
internalError(n.info, "no default for")
|
n.typ = s.typ
|
||||||
result = emptyNode
|
return n
|
||||||
of skType:
|
of skType:
|
||||||
markUsed(n, s)
|
markUsed(n, s)
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
|
||||||
if n.kind != nkGenericParams:
|
if n.kind != nkGenericParams:
|
||||||
internalError(n.info, "instantiateGenericParamList; no generic params")
|
internalError(n.info, "instantiateGenericParamList; no generic params")
|
||||||
newSeq(entry.concreteTypes, n.len)
|
newSeq(entry.concreteTypes, n.len)
|
||||||
for i in countup(0, n.len - 1):
|
for i, a in n.pairs:
|
||||||
var a = n.sons[i]
|
|
||||||
if a.kind != nkSym:
|
if a.kind != nkSym:
|
||||||
internalError(a.info, "instantiateGenericParamList; no symbol")
|
internalError(a.info, "instantiateGenericParamList; no symbol")
|
||||||
var q = a.sym
|
var q = a.sym
|
||||||
|
|
@ -149,7 +148,6 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
info: TLineInfo): PSym =
|
info: TLineInfo): PSym =
|
||||||
# no need to instantiate generic templates/macros:
|
# no need to instantiate generic templates/macros:
|
||||||
if fn.kind in {skTemplate, skMacro}: return fn
|
if fn.kind in {skTemplate, skMacro}: return fn
|
||||||
|
|
||||||
# generates an instantiated proc
|
# generates an instantiated proc
|
||||||
if c.instCounter > 1000: internalError(fn.ast.info, "nesting too deep")
|
if c.instCounter > 1000: internalError(fn.ast.info, "nesting too deep")
|
||||||
inc(c.instCounter)
|
inc(c.instCounter)
|
||||||
|
|
@ -183,9 +181,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
pragma(c, result, n.sons[pragmasPos], allRoutinePragmas)
|
pragma(c, result, n.sons[pragmasPos], allRoutinePragmas)
|
||||||
if isNil(n.sons[bodyPos]):
|
if isNil(n.sons[bodyPos]):
|
||||||
n.sons[bodyPos] = copyTree(fn.getBody)
|
n.sons[bodyPos] = copyTree(fn.getBody)
|
||||||
if fn.kind != skTemplate:
|
instantiateBody(c, n, result)
|
||||||
instantiateBody(c, n, result)
|
sideEffectsCheck(c, result)
|
||||||
sideEffectsCheck(c, result)
|
|
||||||
paramsTypeCheck(c, result.typ)
|
paramsTypeCheck(c, result.typ)
|
||||||
else:
|
else:
|
||||||
result = oldPrc
|
result = oldPrc
|
||||||
|
|
|
||||||
|
|
@ -203,6 +203,14 @@ proc nMinusOne(n: PNode): PNode =
|
||||||
newSymNode(getSysMagic("<", mUnaryLt)),
|
newSymNode(getSysMagic("<", mUnaryLt)),
|
||||||
n])
|
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 =
|
proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||||
var indx, base: PType
|
var indx, base: PType
|
||||||
result = newOrPrevType(tyArray, prev, c)
|
result = newOrPrevType(tyArray, prev, c)
|
||||||
|
|
@ -220,7 +228,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||||
internalAssert c.inGenericContext > 0
|
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)
|
||||||
indx = e.typ
|
indx = makeRangeWithStaticExpr(c, e)
|
||||||
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)
|
||||||
|
|
@ -229,12 +237,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||||
# We are going to construct a range type that will be
|
# We are going to construct a range type that will be
|
||||||
# properly filled-out in semtypinst (see how tyStaticExpr
|
# properly filled-out in semtypinst (see how tyStaticExpr
|
||||||
# is handled there).
|
# is handled there).
|
||||||
let intType = getSysType(tyInt)
|
indx = makeRangeWithStaticExpr(c, e)
|
||||||
indx = newTypeS(tyRange, c)
|
|
||||||
indx.sons = @[intType]
|
|
||||||
indx.n = newNode(nkRange, n.info, @[
|
|
||||||
newIntTypeNode(nkIntLit, 0, intType),
|
|
||||||
makeStaticExpr(c, e.nMinusOne)])
|
|
||||||
else:
|
else:
|
||||||
indx = e.typ.skipTypes({tyTypeDesc})
|
indx = e.typ.skipTypes({tyTypeDesc})
|
||||||
addSonSkipIntLit(result, indx)
|
addSonSkipIntLit(result, indx)
|
||||||
|
|
@ -283,6 +286,18 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||||
result = result.typ.sym.copySym
|
result = result.typ.sym.copySym
|
||||||
result.typ = copyType(result.typ, result.typ.owner, true)
|
result.typ = copyType(result.typ, result.typ.owner, true)
|
||||||
result.typ.flags.incl tfUnresolved
|
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:
|
if result.kind != skType:
|
||||||
# this implements the wanted ``var v: V, x: V`` feature ...
|
# this implements the wanted ``var v: V, x: V`` feature ...
|
||||||
var ov: TOverloadIter
|
var ov: TOverloadIter
|
||||||
|
|
@ -787,11 +802,9 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
result = addImplicitGeneric(newTypeS(tyAnything, c))
|
result = addImplicitGeneric(newTypeS(tyAnything, c))
|
||||||
|
|
||||||
of tyGenericParam:
|
of tyGenericParam:
|
||||||
if tfGenericTypeParam in paramType.flags and false:
|
if tfWildcard in paramType.flags:
|
||||||
if paramType.sonsLen > 0:
|
paramType.flags.excl tfWildcard
|
||||||
result = liftingWalk(paramType.lastSon)
|
paramType.sym.kind = skType
|
||||||
else:
|
|
||||||
result = addImplicitGeneric(newTypeS(tyAnything, c))
|
|
||||||
|
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
|
|
@ -894,6 +907,12 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
result.sons[0] = r
|
result.sons[0] = r
|
||||||
res.typ = 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 =
|
proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
var length = sonsLen(n)
|
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)
|
localError(n.info, errNoGenericParamsAllowedForX, s.name.s)
|
||||||
return newOrPrevType(tyError, prev, c)
|
return newOrPrevType(tyError, prev, c)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
var m = newCandidate(c, s, n)
|
var m = newCandidate(c, s, n)
|
||||||
matches(c, n, copyTree(n), m)
|
matches(c, n, copyTree(n), m)
|
||||||
|
|
||||||
|
|
@ -1262,6 +1280,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||||
|
|
||||||
if typ == nil:
|
if typ == nil:
|
||||||
typ = newTypeS(tyGenericParam, c)
|
typ = newTypeS(tyGenericParam, c)
|
||||||
|
if father == nil: typ.flags.incl tfWildcard
|
||||||
|
|
||||||
typ.flags.incl tfGenericTypeParam
|
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
|
# type for each generic param. the index
|
||||||
# of the parameter will be stored in the
|
# of the parameter will be stored in the
|
||||||
# attached symbol.
|
# attached symbol.
|
||||||
var s = case finalType.kind
|
var s = if finalType.kind == tyStatic or tfWildcard in typ.flags:
|
||||||
of tyStatic:
|
|
||||||
newSymG(skGenericParam, a.sons[j], c).linkTo(finalType)
|
newSymG(skGenericParam, a.sons[j], c).linkTo(finalType)
|
||||||
else:
|
else:
|
||||||
newSymG(skType, a.sons[j], c).linkTo(finalType)
|
newSymG(skType, a.sons[j], c).linkTo(finalType)
|
||||||
|
|
|
||||||
|
|
@ -395,20 +395,10 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
|
|
||||||
result.n = replaceTypeVarsN(cl, result.n)
|
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
|
case result.kind
|
||||||
of tyArray:
|
of tyArray:
|
||||||
let idx = result.sons[0]
|
let idx = result.sons[0]
|
||||||
if idx.kind == tyStatic:
|
internalAssert 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)
|
|
||||||
|
|
||||||
of tyObject, tyTuple:
|
of tyObject, tyTuple:
|
||||||
propagateFieldFlags(result, result.n)
|
propagateFieldFlags(result, result.n)
|
||||||
|
|
|
||||||
|
|
@ -620,8 +620,10 @@ 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: result = isNone
|
if result < isGeneric:
|
||||||
elif lengthOrd(fRange) != lengthOrd(a): result = isNone
|
result = isNone
|
||||||
|
elif lengthOrd(fRange) != lengthOrd(a):
|
||||||
|
result = isNone
|
||||||
else: discard
|
else: discard
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
case a.kind
|
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
|
# any value" and what we need is "match any type", which can be encoded
|
||||||
# by a tyTypeDesc params. Unfortunately, this requires more substantial
|
# by a tyTypeDesc params. Unfortunately, this requires more substantial
|
||||||
# changes in semtypinst and elsewhere.
|
# changes in semtypinst and elsewhere.
|
||||||
if a.kind == tyTypeDesc:
|
if a.kind == tyTypeDesc or tfWildcard in a.flags:
|
||||||
if f.sonsLen == 0:
|
if f.sonsLen == 0:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
else:
|
else:
|
||||||
|
|
@ -883,11 +885,16 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
|
|
||||||
if result == isGeneric:
|
if result == isGeneric:
|
||||||
var concrete = concreteType(c, a)
|
var concrete = a
|
||||||
if concrete == nil:
|
if tfWildcard in a.flags:
|
||||||
result = isNone
|
a.sym.kind = skType
|
||||||
|
a.flags.excl tfWildcard
|
||||||
else:
|
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:
|
elif a.kind == tyEmpty:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
elif x.kind == tyGenericParam:
|
elif x.kind == tyGenericParam:
|
||||||
|
|
@ -1030,6 +1037,15 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
# 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
|
||||||
# make sure that static types enter here
|
# 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)
|
var evaluated = c.semTryConstExpr(c, arg)
|
||||||
if evaluated != nil:
|
if evaluated != nil:
|
||||||
arg.typ = newTypeS(tyStatic, c)
|
arg.typ = newTypeS(tyStatic, c)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue