first phase of tyGenericParam reforms needed for static params

This commit is contained in:
Zahary Karadjov
2014-03-15 19:23:20 +02:00
parent 4d2c948281
commit 37b199d34a
6 changed files with 79 additions and 47 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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