diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 3 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 4 | ||||
-rw-r--r-- | compiler/semexprs.nim | 39 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 20 | ||||
-rw-r--r-- | compiler/types.nim | 20 | ||||
-rw-r--r-- | compiler/vmdeps.nim | 11 |
6 files changed, 52 insertions, 45 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index bd244fb97..f13691d54 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -428,6 +428,7 @@ const tyAnd, tyOr, tyNot, tyAnything} tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyExpr} + tyTypeClasses + tyUserTypeClasses* = {tyUserTypeClass, tyUserTypeClassInst} type TTypeKinds* = set[TTypeKind] @@ -471,6 +472,8 @@ type # can be attached to generic procs with free standing # type parameters: e.g. proc foo[T]() # depends on unresolved static params. + tfResolved # marks a user type class, after it has been bound to a + # concrete type (lastSon becomes the concrete type) tfRetType, # marks return types in proc (used to detect type classes # used as return types for return type inference) tfCapturesEnv, # whether proc really captures some environment diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 309fb1f20..6e10379e6 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -890,7 +890,7 @@ proc genSeqElem(p: BProc, x, y: PNode, d: var TLoc) = rfmt(nil, "$1->data[$2]", rdLoc(a), rdCharLoc(b)), a.s) proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) = - var ty = skipTypes(n.sons[0].typ, abstractVarRange) + var ty = skipTypes(n.sons[0].typ, abstractVarRange + tyUserTypeClasses) if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange) case ty.kind of tyArray: genArrayElem(p, n.sons[0], n.sons[1], d) @@ -1359,7 +1359,7 @@ proc genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) = proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = var a = e.sons[1] if a.kind == nkHiddenAddr: a = a.sons[0] - let typ = skipTypes(a.typ, abstractVar) + var typ = skipTypes(a.typ, abstractVar + tyUserTypeClasses) case typ.kind of tyOpenArray, tyVarargs: if op == mHigh: unaryExpr(p, e, d, "($1Len_0-1)") diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 475f496f1..3ec2cd391 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -136,6 +136,7 @@ proc isCastable(dst, src: PType): bool = # castableTypeKinds = {tyInt, tyPtr, tyRef, tyCstring, tyString, # tySequence, tyPointer, tyNil, tyOpenArray, # tyProc, tySet, tyEnum, tyBool, tyChar} + let src = src.skipTypes(tyUserTypeClasses) if skipTypes(dst, abstractInst-{tyOpenArray}).kind == tyOpenArray: return false if skipTypes(src, abstractInst-{tyTypeDesc}).kind == tyTypeDesc: @@ -908,28 +909,14 @@ proc makeDeref(n: PNode): PNode = t = skipTypes(baseTyp, {tyGenericInst, tyAlias}) const - tyTypeParamsHolders = {tyGenericInst, tyUserTypeClassInst, tyCompositeTypeClass} + tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass, + tyUserTypeClass, tyUserTypeClassInst} tyDotOpTransparent = {tyVar, tyPtr, tyRef, tyAlias} proc readTypeParameter(c: PContext, typ: PType, paramName: PIdent, info: TLineInfo): PNode = - let ty = if typ.kind in {tyGenericInst, tyUserTypeClassInst}: typ.skipGenericAlias - else: (internalAssert(typ.kind == tyCompositeTypeClass); - typ.sons[1].skipGenericAlias) - - let tbody = ty.sons[0] - for s in countup(0, tbody.len-2): - let tParam = tbody.sons[s] - if tParam.sym.name.id == paramName.id: - let rawTyp = ty.sons[s + 1] - if rawTyp.kind == tyStatic: - return rawTyp.n - else: - let foundTyp = makeTypeDesc(c, rawTyp) - return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info) - - if ty.n != nil: - for statement in ty.n: + if typ.kind in {tyUserTypeClass, tyUserTypeClassInst}: + for statement in typ.n: case statement.kind of nkTypeSection: for def in statement: @@ -939,7 +926,7 @@ proc readTypeParameter(c: PContext, typ: PType, # This seems semantically correct and then we'll be able # to return the section symbol directly here let foundType = makeTypeDesc(c, def[2].typ) - return newSymNode(copySym(def[2].sym).linkTo(foundType), info) + return newSymNode(copySym(def[0].sym).linkTo(foundType), info) of nkConstSection: for def in statement: @@ -948,6 +935,20 @@ proc readTypeParameter(c: PContext, typ: PType, else: discard + + if typ.kind != tyUserTypeClass: + let ty = if typ.kind == tyCompositeTypeClass: typ.sons[1].skipGenericAlias + else: typ.skipGenericAlias + let tbody = ty.sons[0] + for s in countup(0, tbody.len-2): + let tParam = tbody.sons[s] + if tParam.sym.name.id == paramName.id: + let rawTyp = ty.sons[s + 1] + if rawTyp.kind == tyStatic: + return rawTyp.n + else: + let foundTyp = makeTypeDesc(c, rawTyp) + return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info) return nil diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index f33ac76e7..162385e6d 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1197,22 +1197,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = else: return isNone - of tyUserTypeClass: - considerPreviousT: - var matched = matchUserTypeClass(c.c, c, f, aOrig) - if matched != nil: - # TODO, make user type classes skipable too - put(c, f, a) - result = isGeneric - else: - result = isNone - - of tyUserTypeClassInst: - considerPreviousT: + of tyUserTypeClassInst, tyUserTypeClass: + if f.isResolvedUserTypeClass: + result = typeRel(c, f.lastSon, a) + else: var matched = matchUserTypeClass(c.c, c, f, aOrig) if matched != nil: - matched.sons.add a - put(c.bindings, f, matched) + bindConcreteTypeToUserTypeClass(matched, a) + put(c, f, matched) result = isGeneric else: result = isNone diff --git a/compiler/types.nim b/compiler/types.nim index 3e124412b..be7028f9c 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -63,7 +63,7 @@ const abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias, tyInferred} abstractInst* = {tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias, - tyInferred} + tyInferred} + tyTypeClasses skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyTypeDesc, tyAlias, tyInferred} # typedescX is used if we're sure tyTypeDesc should be included (or skipped) @@ -417,6 +417,13 @@ const const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg} +template bindConcreteTypeToUserTypeClass*(tc, concrete: PType) = + tc.sons.safeAdd concrete + tc.flags.incl tfResolved + +template isResolvedUserTypeClass*(t: PType): bool = + tfResolved in t.flags + proc addTypeFlags(name: var string, typ: PType) {.inline.} = if tfNotNil in typ.flags: name.add(" not nil") @@ -461,6 +468,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = if t.n != nil: result.add "(" & renderTree(t.n) & ")" of tyUserTypeClass: internalAssert t.sym != nil and t.sym.owner != nil + if t.isResolvedUserTypeClass: return typeToString(t.lastSon) return t.sym.owner.name.s of tyBuiltInTypeClass: result = case t.base.kind: @@ -1314,12 +1322,15 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt = result = align(result, a) of tyGenericInst, tyDistinct, tyGenericBody, tyAlias: result = computeSizeAux(lastSon(typ), a) + of tyTypeClasses: + result = if typ.isResolvedUserTypeClass: computeSizeAux(typ.lastSon, a) + else: szUnknownSize of tyTypeDesc: result = computeSizeAux(typ.base, a) of tyForward: return szIllegalRecursion of tyStatic: - if typ.n != nil: result = computeSizeAux(lastSon(typ), a) - else: result = szUnknownSize + result = if typ.n != nil: computeSizeAux(typ.lastSon, a) + else: szUnknownSize else: #internalError("computeSizeAux()") result = szUnknownSize @@ -1492,9 +1503,6 @@ proc isEmptyContainer*(t: PType): bool = of tyGenericInst, tyAlias: result = isEmptyContainer(t.lastSon) else: result = false -proc isResolvedUserTypeClass*(t: PType): bool = - t.kind in {tyUserTypeClassInst} and t.base.sonsLen == t.sonsLen - 2 - proc takeType*(formal, arg: PType): PType = # param: openArray[string] = [] # [] is an array constructor of length 0 of type string! diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 7094d174b..8c7388643 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -175,7 +175,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo; result.add mapTypeToAst(t.sons[i], info) else: result = mapTypeToAstX(t.lastSon, info, inst, allowRecursion) - of tyGenericBody, tyOrdinal, tyUserTypeClassInst: + of tyGenericBody, tyOrdinal: result = mapTypeToAst(t.lastSon, info) of tyDistinct: if inst: @@ -285,9 +285,12 @@ proc mapTypeToAstX(t: PType; info: TLineInfo; of tyProxy: result = atomicType("error", mNone) of tyBuiltInTypeClass: result = mapTypeToBracket("builtinTypeClass", mNone, t, info) - of tyUserTypeClass: - result = mapTypeToBracket("concept", mNone, t, info) - result.add t.n.copyTree + of tyUserTypeClass, tyUserTypeClassInst: + if t.isResolvedUserTypeClass: + result = mapTypeToAst(t.lastSon, info) + else: + result = mapTypeToBracket("concept", mNone, t, info) + result.add t.n.copyTree of tyCompositeTypeClass: result = mapTypeToBracket("compositeTypeClass", mNone, t, info) of tyAnd: result = mapTypeToBracket("and", mAnd, t, info) |