diff options
author | Zahary Karadjov <zahary@gmail.com> | 2014-03-15 19:23:20 +0200 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2014-03-16 20:42:06 +0200 |
commit | 37b199d34ae198872f061d9a4155539138b34c87 (patch) | |
tree | 3309c8ba5f394e5cfbb65ffa51f1c7c96e6eb7a3 /compiler | |
parent | 4d2c948281ee1ad38f8098d1b454dc4787441e8b (diff) | |
download | Nim-37b199d34ae198872f061d9a4155539138b34c87.tar.gz |
first phase of tyGenericParam reforms needed for static params
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 13 | ||||
-rw-r--r-- | compiler/semexprs.nim | 4 | ||||
-rw-r--r-- | compiler/seminst.nim | 9 | ||||
-rw-r--r-- | compiler/semtypes.nim | 54 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 14 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 32 |
6 files changed, 79 insertions, 47 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index ee0d55920..55de43dd1 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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 diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index ba2847835..133b4ac1e 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -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) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 4bcfa7f15..dca9e3378 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -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 diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index f91222477..6e47af837 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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) diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 80e2aa284..f8cddd781 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -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) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 19f10def8..049c9520b 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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) |