diff options
-rw-r--r-- | compiler/semexprs.nim | 27 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 35 | ||||
-rw-r--r-- | tests/concepts/tstackconcept.nim | 19 |
3 files changed, 65 insertions, 16 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index a14bc6c79..b3fe83ed8 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -912,11 +912,14 @@ const tyTypeParamsHolders = {tyGenericInst, tyUserTypeClassInst, tyCompositeTypeClass} 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] @@ -927,7 +930,29 @@ proc readTypeParameter(c: PContext, typ: PType, else: let foundTyp = makeTypeDesc(c, rawTyp) return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info) - #echo "came here: returned nil" + + if ty.n != nil: + for statement in ty.n: + case statement.kind + of nkTypeSection: + for def in statement: + if def[0].sym.name.id == paramName.id: + # XXX: Instead of lifting the section type to a typedesc + # here, we could try doing it earlier in semTypeSection. + # 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) + + of nkConstSection: + for def in statement: + if def[0].sym.name.id == paramName.id: + return def[2] + + else: + discard + + return nil proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = let s = getGenSym(c, sym) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index f8004fa21..f819af13d 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -572,11 +572,11 @@ proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} = result = isNone proc matchUserTypeClass*(c: PContext, m: var TCandidate, - ff, a: PType): TTypeRelation = + ff, a: PType): PType = var body = ff.skipTypes({tyUserTypeClassInst}) if c.inTypeClass > 4: localError(body.n[3].info, $body.n[3] & " too nested for type matching") - return isNone + return nil openScope(c) inc c.inTypeClass @@ -636,7 +636,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate, #echo "B ", dummyName.ident.s, " ", typeToString(dummyType), " ", dummyparam.kind var checkedBody = c.semTryExpr(c, body.n[3].copyTree) - if checkedBody == nil: return isNone + if checkedBody == nil: return nil # The inferrable type params have been identified during the semTryExpr above. # We need to put them in the current sigmatch's binding table in order for them @@ -644,7 +644,12 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate, for p in typeParams: put(m.bindings, p[1], p[0].typ) - return isGeneric + if ff.kind == tyUserTypeClassInst: + result = generateTypeInstance(c, m.bindings, m.call.info, ff) + else: + result = copyType(ff, ff.owner, true) + + result.n = checkedBody proc shouldSkipDistinct(rules: PNode, callIdent: PIdent): bool = if rules.kind == nkWith: @@ -1130,17 +1135,23 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = of tyUserTypeClass: considerPreviousT: - result = matchUserTypeClass(c.c, c, f, aOrig) - if result == isGeneric: + 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: - result = matchUserTypeClass(c.c, c, f, aOrig) - if result == isGeneric: - var fWithResolvedParams = generateTypeInstance(c.c, c.bindings, c.call.info, f) - fWithResolvedParams.sons.add a - put(c.bindings, f, fWithResolvedParams) + var matched = matchUserTypeClass(c.c, c, f, aOrig) + if matched != nil: + matched.sons.add a + put(c.bindings, f, matched) + result = isGeneric + else: + result = isNone of tyCompositeTypeClass: considerPreviousT: @@ -1408,7 +1419,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, arg = argSemantized argType = argType c = m.c - + if inferTypeClassParam(c, f, argType): return argSemantized diff --git a/tests/concepts/tstackconcept.nim b/tests/concepts/tstackconcept.nim index dc75df5ff..11d6505cf 100644 --- a/tests/concepts/tstackconcept.nim +++ b/tests/concepts/tstackconcept.nim @@ -2,11 +2,15 @@ discard """ output: "20\n10" msg: ''' INFERRED int +VALUE TYPE int +VALUE TYPE NAME INT IMPLICIT INFERRED int int +IMPLICIT VALUE TYPE int int +IMPLICIT VALUE TYPE NAME INT INT ''' """ -import typetraits +import typetraits, strutils template reject(e: expr) = static: assert(not compiles(e)) @@ -26,14 +30,23 @@ type s.push(T) s.pop() is T + type ValueType = T + const ValueTypeName = T.name.toUpper + proc genericAlgorithm[T](s: var Stack[T], y: T) = - static: echo "INFERRED ", T.name + static: + echo "INFERRED ", T.name + echo "VALUE TYPE ", s.ValueType.name + echo "VALUE TYPE NAME ", s.ValueTypeName s.push(y) echo s.pop proc implicitGeneric(s: var Stack): auto = - static: echo "IMPLICIT INFERRED ", s.T.name, " ", Stack.T.name + static: + echo "IMPLICIT INFERRED ", s.T.name, " ", Stack.T.name + echo "IMPLICIT VALUE TYPE ", s.ValueType.name, " ", Stack.ValueType.name + echo "IMPLICIT VALUE TYPE NAME ", s.ValueTypeName, " ", s.ValueTypeName return s.pop() |