type constraints; tuple lifting

This commit is contained in:
Araq
2011-04-01 00:26:07 +02:00
parent dc669155e3
commit 4d91c9d887
17 changed files with 527 additions and 139 deletions

View File

@@ -237,7 +237,7 @@ type
tyGenericParam, # ``a`` in the example
tyDistinct,
tyEnum,
tyOrdinal,
tyOrdinal, # misnamed: should become 'tyConstraint'
tyArray,
tyObject,
tyTuple,
@@ -329,7 +329,9 @@ type
mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr,
mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet,
mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT,
mConTArr, mConTT, mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem,
mConTArr, mConTT, mSlice,
mFields, mFieldPairs,
mAppendStrCh, mAppendStrStr, mAppendSeqElem,
mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, mAssert,
mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, mNewString, mReset,
mArray, mOpenArray, mRange, mSet, mSeq,

View File

@@ -1014,12 +1014,77 @@ proc parseAsm(p: var TParser): PNode =
return
getTok(p)
proc parseGenericConstraint(p: var TParser): PNode =
case p.tok.tokType
of tkObject:
result = newNodeP(nkObjectTy, p)
getTok(p)
of tkTuple:
result = newNodeP(nkTupleTy, p)
getTok(p)
of tkEnum:
result = newNodeP(nkEnumTy, p)
getTok(p)
of tkProc:
result = newNodeP(nkProcTy, p)
getTok(p)
of tkVar:
result = newNodeP(nkVarTy, p)
getTok(p)
of tkPtr:
result = newNodeP(nkPtrTy, p)
getTok(p)
of tkRef:
result = newNodeP(nkRefTy, p)
getTok(p)
of tkDistinct:
result = newNodeP(nkDistinctTy, p)
getTok(p)
else: result = primary(p)
proc parseGenericConstraintList(p: var TParser): PNode =
result = parseGenericConstraint(p)
while p.tok.tokType == tkOpr:
var a = result
result = newNodeP(nkInfix, p)
addSon(result, newIdentNodeP(p.tok.ident, p))
addSon(result, a)
getTok(p)
optInd(p, result)
addSon(result, parseGenericConstraint(p))
proc parseGenericParam(p: var TParser): PNode =
var a: PNode
result = newNodeP(nkIdentDefs, p)
while true:
case p.tok.tokType
of tkSymbol, tkAccent:
a = parseSymbol(p)
if a.kind == nkEmpty: return
else: break
addSon(result, a)
if p.tok.tokType != tkComma: break
getTok(p)
optInd(p, a)
if p.tok.tokType == tkColon:
getTok(p)
optInd(p, result)
addSon(result, parseGenericConstraintList(p))
else:
addSon(result, ast.emptyNode)
if p.tok.tokType == tkEquals:
getTok(p)
optInd(p, result)
addSon(result, parseExpr(p))
else:
addSon(result, ast.emptyNode)
proc parseGenericParamList(p: var TParser): PNode =
result = newNodeP(nkGenericParams, p)
getTok(p)
optInd(p, result)
while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent):
var a = parseIdentColonEquals(p, {withBothOptional})
var a = parseGenericParam(p)
addSon(result, a)
if p.tok.tokType != tkComma: break
getTok(p)

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -839,17 +839,29 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
putWithSpace(g, tkType, "type")
gsub(g, n.sons[0])
of nkRefTy:
putWithSpace(g, tkRef, "ref")
gsub(g, n.sons[0])
if sonsLen(n) > 0:
putWithSpace(g, tkRef, "ref")
gsub(g, n.sons[0])
else:
put(g, tkRef, "ref")
of nkPtrTy:
putWithSpace(g, tkPtr, "ptr")
gsub(g, n.sons[0])
if sonsLen(n) > 0:
putWithSpace(g, tkPtr, "ptr")
gsub(g, n.sons[0])
else:
put(g, tkPtr, "ptr")
of nkVarTy:
putWithSpace(g, tkVar, "var")
gsub(g, n.sons[0])
if sonsLen(n) > 0:
putWithSpace(g, tkVar, "var")
gsub(g, n.sons[0])
else:
put(g, tkVar, "var")
of nkDistinctTy:
putWithSpace(g, tkDistinct, "distinct")
gsub(g, n.sons[0])
if sonsLen(n) > 0:
putWithSpace(g, tkDistinct, "distinct")
gsub(g, n.sons[0])
else:
put(g, tkDistinct, "distinct")
of nkTypeDef:
gsub(g, n.sons[0])
gsub(g, n.sons[1])
@@ -858,11 +870,14 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
putWithSpace(g, tkEquals, "=")
gsub(g, n.sons[2])
of nkObjectTy:
putWithSpace(g, tkObject, "object")
gsub(g, n.sons[0])
gsub(g, n.sons[1])
gcoms(g)
gsub(g, n.sons[2])
if sonsLen(n) > 0:
putWithSpace(g, tkObject, "object")
gsub(g, n.sons[0])
gsub(g, n.sons[1])
gcoms(g)
gsub(g, n.sons[2])
else:
put(g, tkObject, "object")
of nkRecList:
indentNL(g)
for i in countup(0, sonsLen(n) - 1):
@@ -875,17 +890,23 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
putWithSpace(g, tkOf, "of")
gsub(g, n.sons[0])
of nkProcTy:
putWithSpace(g, tkProc, "proc")
gsub(g, n.sons[0])
gsub(g, n.sons[1])
if sonsLen(n) > 0:
putWithSpace(g, tkProc, "proc")
gsub(g, n.sons[0])
gsub(g, n.sons[1])
else:
put(g, tkProc, "proc")
of nkEnumTy:
putWithSpace(g, tkEnum, "enum")
gsub(g, n.sons[0])
gcoms(g)
indentNL(g)
gcommaAux(g, n, g.indent, 1)
gcoms(g) # BUGFIX: comment for the last enum field
dedent(g)
if sonsLen(n) > 0:
putWithSpace(g, tkEnum, "enum")
gsub(g, n.sons[0])
gcoms(g)
indentNL(g)
gcommaAux(g, n, g.indent, 1)
gcoms(g) # BUGFIX: comment for the last enum field
dedent(g)
else:
put(g, tkEnum, "enum")
of nkEnumFieldDef:
gsub(g, n.sons[0])
put(g, tkSpaces, Space)
@@ -1033,9 +1054,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
gsub(g, n.sons[0])
of nkTupleTy:
put(g, tkTuple, "tuple")
put(g, tkBracketLe, "[")
gcomma(g, n)
put(g, tkBracketRi, "]")
if sonsLen(n) > 0:
put(g, tkBracketLe, "[")
gcomma(g, n)
put(g, tkBracketRi, "]")
else:
#nkNone, nkMetaNode, nkTableConstr, nkExplicitTypeListCall:
InternalError(n.info, "rnimsyn.gsub(" & $n.kind & ')')

View File

@@ -118,7 +118,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
c.p = oldP # restore
c.module = oldMod
dec(c.InstCounter)
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
var cl: TReplTypeVars
InitIdTable(cl.symMap)

View File

@@ -358,49 +358,120 @@ proc semConst(c: PContext, n: PNode): PNode =
addSon(b, copyTree(def))
addSon(result, b)
proc transfFieldLoopBody(n: PNode, forLoop: PNode,
tupleType: PType,
tupleIndex, first: int): PNode =
case n.kind
of nkEmpty..pred(nkIdent), succ(nkIdent)..nkNilLit: result = n
of nkIdent:
result = n
var L = sonsLen(forLoop)
# field name:
if first > 0:
if n.ident.id == forLoop[0].ident.id:
if tupleType.n == nil:
# ugh, there are no field names:
result = newStrNode(nkStrLit, "")
else:
result = newStrNode(nkStrLit, tupleType.n.sons[tupleIndex].sym.name.s)
return
# other fields:
for i in first..L-3:
if n.ident.id == forLoop[i].ident.id:
var call = forLoop.sons[L-2]
var tupl = call.sons[i+1-first]
result = newNodeI(nkBracketExpr, n.info)
result.add(tupl)
result.add(newIntNode(nkIntLit, tupleIndex))
break
else:
result = copyNode(n)
newSons(result, sonsLen(n))
for i in countup(0, sonsLen(n)-1):
result.sons[i] = transfFieldLoopBody(n.sons[i], forLoop,
tupleType, tupleIndex, first)
proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
# so that 'break' etc. work as expected, we produce
# a 'while true: stmt; break' loop ...
result = newNodeI(nkWhileStmt, n.info)
var trueSymbol = StrTableGet(magicsys.systemModule.Tab, getIdent"true")
if trueSymbol == nil: GlobalError(n.info, errSystemNeeds, "true")
result.add(newSymNode(trueSymbol, n.info))
var stmts = newNodeI(nkStmtList, n.info)
result.add(stmts)
var length = sonsLen(n)
var call = n.sons[length-2]
if length-2 != sonsLen(call)-1 + ord(m==mFieldPairs):
GlobalError(n.info, errWrongNumberOfVariables)
var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar)
if tupleTypeA.kind != tyTuple: InternalError(n.info, "no tuple type!")
for i in 1..call.len-1:
var tupleTypeB = skipTypes(call.sons[i].typ, abstractVar)
if not SameType(tupleTypeA, tupleTypeB):
typeMismatch(call.sons[i], tupleTypeA, tupleTypeB)
Inc(c.p.nestedLoopCounter)
var loopBody = n.sons[length-1]
for i in 0..sonsLen(tupleTypeA)-1:
openScope(c.tab)
var body = transfFieldLoopBody(loopBody, n, tupleTypeA, i,
ord(m==mFieldPairs))
stmts.add(SemStmt(c, body))
closeScope(c.tab)
Dec(c.p.nestedLoopCounter)
var b = newNodeI(nkBreakStmt, n.info)
b.add(ast.emptyNode)
stmts.add(b)
proc createCountupNode(c: PContext, rangeNode: PNode): PNode =
# convert ``in 3..5`` to ``in countup(3, 5)``
checkSonsLen(rangeNode, 2)
result = newNodeI(nkCall, rangeNode.info)
var countUp = StrTableGet(magicsys.systemModule.Tab, getIdent"countup")
if countUp == nil: GlobalError(rangeNode.info, errSystemNeeds, "countup")
newSons(result, 3)
result.sons[0] = newSymNode(countup)
result.sons[1] = rangeNode.sons[0]
result.sons[2] = rangeNode.sons[1]
proc semFor(c: PContext, n: PNode): PNode =
var
v, countup: PSym
iter: PType
countupNode, call: PNode
result = n
checkMinSonsLen(n, 3)
var length = sonsLen(n)
openScope(c.tab)
if n.sons[length - 2].kind == nkRange:
checkSonsLen(n.sons[length - 2], 2)
# convert ``in 3..5`` to ``in countup(3, 5)``
countupNode = newNodeI(nkCall, n.sons[length - 2].info)
countUp = StrTableGet(magicsys.systemModule.Tab, getIdent("countup"))
if countUp == nil: GlobalError(countupNode.info, errSystemNeeds, "countup")
newSons(countupNode, 3)
countupnode.sons[0] = newSymNode(countup)
countupNode.sons[1] = n.sons[length - 2].sons[0]
countupNode.sons[2] = n.sons[length - 2].sons[1]
n.sons[length - 2] = countupNode
n.sons[length - 2] = semExprWithType(c, n.sons[length - 2], {efWantIterator})
call = n.sons[length - 2]
if (call.kind != nkCall) or (call.sons[0].kind != nkSym) or
(call.sons[0].sym.kind != skIterator):
if n.sons[length-2].kind == nkRange:
n.sons[length-2] = createCountupNode(c, n.sons[length-2])
n.sons[length-2] = semExprWithType(c, n.sons[length-2], {efWantIterator})
var call = n.sons[length-2]
if call.kind != nkCall or call.sons[0].kind != nkSym or
call.sons[0].sym.kind != skIterator:
GlobalError(n.sons[length - 2].info, errIteratorExpected)
iter = skipTypes(n.sons[length - 2].typ, {tyGenericInst})
if iter.kind != tyTuple:
if length != 3: GlobalError(n.info, errWrongNumberOfVariables)
v = newSymS(skForVar, n.sons[0], c)
v.typ = iter
n.sons[0] = newSymNode(v)
addDecl(c, v)
else:
if length-2 != sonsLen(iter): GlobalError(n.info, errWrongNumberOfVariables)
for i in countup(0, length - 3):
v = newSymS(skForVar, n.sons[i], c)
v.typ = iter.sons[i]
n.sons[i] = newSymNode(v)
elif call.sons[0].sym.magic != mNone:
result = semForFields(c, n, call.sons[0].sym.magic)
else:
var iter = skipTypes(n.sons[length-2].typ, {tyGenericInst})
if iter.kind != tyTuple:
if length != 3: GlobalError(n.info, errWrongNumberOfVariables)
var v = newSymS(skForVar, n.sons[0], c)
v.typ = iter
n.sons[0] = newSymNode(v)
addDecl(c, v)
Inc(c.p.nestedLoopCounter)
n.sons[length - 1] = SemStmt(c, n.sons[length - 1])
else:
if length-2 != sonsLen(iter):
GlobalError(n.info, errWrongNumberOfVariables)
for i in countup(0, length - 3):
var v = newSymS(skForVar, n.sons[i], c)
v.typ = iter.sons[i]
n.sons[i] = newSymNode(v)
addDecl(c, v)
Inc(c.p.nestedLoopCounter)
n.sons[length-1] = SemStmt(c, n.sons[length-1])
Dec(c.p.nestedLoopCounter)
closeScope(c.tab)
Dec(c.p.nestedLoopCounter)
proc semRaise(c: PContext, n: PNode): PNode =
result = n
@@ -436,34 +507,6 @@ proc semTry(c: PContext, n: PNode): PNode =
# last child of an nkExcept/nkFinally branch is a statement:
a.sons[length - 1] = semStmtScope(c, a.sons[length - 1])
proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
result = copyNode(n)
if n.kind != nkGenericParams: InternalError(n.info, "semGenericParamList")
for i in countup(0, sonsLen(n)-1):
var a = n.sons[i]
if a.kind != nkIdentDefs: illFormedAst(n)
var L = sonsLen(a)
var def = a.sons[L-1]
var typ: PType
if a.sons[L-2].kind != nkEmpty: typ = semTypeNode(c, a.sons[L-2], nil)
elif def.kind != nkEmpty: typ = newTypeS(tyExpr, c)
else: typ = nil
for j in countup(0, L-3):
var s: PSym
if (typ == nil) or (typ.kind == tyTypeDesc):
s = newSymS(skType, a.sons[j], c)
s.typ = newTypeS(tyGenericParam, c)
else:
# not a type param, but an expression
s = newSymS(skGenericParam, a.sons[j], c)
s.typ = typ
if def.kind != nkEmpty: s.ast = def
s.typ.sym = s
if father != nil: addSon(father, s.typ)
s.position = i
addSon(result, newSymNode(s))
addDecl(c, s)
proc addGenericParamListToScope(c: PContext, n: PNode) =
if n.kind != nkGenericParams:
InternalError(n.info, "addGenericParamListToScope")
@@ -741,7 +784,7 @@ proc semIterator(c: PContext, n: PNode): PNode =
var t = s.typ
if t.sons[0] == nil:
LocalError(n.info, errXNeedsReturnType, "iterator")
if n.sons[codePos].kind == nkEmpty:
if n.sons[codePos].kind == nkEmpty and s.magic == mNone:
LocalError(n.info, errImplOfXexpected, s.name.s)
proc semProc(c: PContext, n: PNode): PNode =

View File

@@ -173,12 +173,12 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
else:
GlobalError(n.info, errXExpectsOneTypeParam, "ordinal")
proc semTypeIdent(c: PContext, n: PNode): PSym =
proc semTypeIdent(c: PContext, n: PNode): PSym =
result = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared})
if (result != nil):
if result != nil:
markUsed(n, result)
if result.kind != skType: GlobalError(n.info, errTypeExpected)
else:
else:
GlobalError(n.info, errIdentifierExpected)
proc semTuple(c: PContext, n: PNode, prev: PType): PType =
@@ -441,8 +441,6 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags:
addInheritedFields(c, check, pos, concreteBase)
else:
debug base
debug concreteBase
localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
if n.kind != nkObjectTy: InternalError(n.info, "semObjectNode")
result = newOrPrevType(tyObject, prev, c)
@@ -632,10 +630,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
proc setMagicType(m: PSym, kind: TTypeKind, size: int) =
m.typ.kind = kind
m.typ.align = size
m.typ.size = size #m.typ.sym := nil;
m.typ.size = size
proc processMagicType(c: PContext, m: PSym) =
case m.magic #registerSysType(m.typ);
case m.magic
of mInt: setMagicType(m, tyInt, intSize)
of mInt8: setMagicType(m, tyInt8, 1)
of mInt16: setMagicType(m, tyInt16, 2)
@@ -656,13 +654,70 @@ proc processMagicType(c: PContext, m: PSym) =
of mEmptySet:
setMagicType(m, tySet, 1)
addSon(m.typ, newTypeS(tyEmpty, c))
of mIntSetBaseType:
setMagicType(m, tyRange, intSize) #intSetBaseType := m.typ;
return
of mIntSetBaseType: setMagicType(m, tyRange, intSize)
of mNil: setMagicType(m, tyNil, ptrSize)
of mExpr: setMagicType(m, tyExpr, 0)
of mStmt: setMagicType(m, tyStmt, 0)
of mTypeDesc: setMagicType(m, tyTypeDesc, 0)
of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: return
of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: nil
else: GlobalError(m.info, errTypeExpected)
proc newConstraint(c: PContext, k: TTypeKind): PType =
result = newTypeS(tyOrdinal, c)
result.addSon(newTypeS(k, c))
proc semGenericConstraints(c: PContext, n: PNode, result: PType) =
case n.kind
of nkProcTy: result.addSon(newConstraint(c, tyProc))
of nkEnumTy: result.addSon(newConstraint(c, tyEnum))
of nkObjectTy: result.addSon(newConstraint(c, tyObject))
of nkTupleTy: result.addSon(newConstraint(c, tyTuple))
of nkDistinctTy: result.addSon(newConstraint(c, tyDistinct))
of nkVarTy: result.addSon(newConstraint(c, tyVar))
of nkPtrTy: result.addSon(newConstraint(c, tyPtr))
of nkRefTy: result.addSon(newConstraint(c, tyRef))
of nkInfix:
semGenericConstraints(c, n.sons[1], result)
semGenericConstraints(c, n.sons[2], result)
else:
result.addSon(semTypeNode(c, n, nil))
proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
result = copyNode(n)
if n.kind != nkGenericParams: InternalError(n.info, "semGenericParamList")
for i in countup(0, sonsLen(n)-1):
var a = n.sons[i]
if a.kind != nkIdentDefs: illFormedAst(n)
var L = sonsLen(a)
var def = a.sons[L-1]
var typ: PType
if a.sons[L-2].kind != nkEmpty:
typ = newTypeS(tyGenericParam, c)
semGenericConstraints(c, a.sons[L-2], typ)
elif def.kind != nkEmpty: typ = newTypeS(tyExpr, c)
else: typ = nil
for j in countup(0, L-3):
var s: PSym
if typ == nil:
s = newSymS(skType, a.sons[j], c)
s.typ = newTypeS(tyGenericParam, c)
else:
case typ.kind
of tyTypeDesc:
s = newSymS(skType, a.sons[j], c)
s.typ = newTypeS(tyGenericParam, c)
of tyExpr:
# not a type param, but an expression
s = newSymS(skGenericParam, a.sons[j], c)
s.typ = typ
else:
s = newSymS(skType, a.sons[j], c)
s.typ = typ
if def.kind != nkEmpty: s.ast = def
s.typ.sym = s
if father != nil: addSon(father, s.typ)
s.position = i
addSon(result, newSymNode(s))
addDecl(c, s)

View File

@@ -32,7 +32,10 @@ type
# for example
TTypeRelation* = enum # order is important!
isNone, isConvertible, isIntConv, isSubtype, isGeneric, isEqual
isNone, isConvertible, isIntConv, isSubtype,
isLifted, # match, but do not change argument type to formal's type!
isGeneric,
isEqual
proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} =
c.exactMatches = 0
@@ -144,8 +147,8 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
else:
var k = skipTypes(a, {tyRange}).kind
if k == f.kind: result = isSubtype
elif (f.kind == tyInt) and (k in {tyInt..tyInt32}): result = isIntConv
elif (k >= min) and (k <= max): result = isConvertible
elif f.kind == tyInt and k in {tyInt..tyInt32}: result = isIntConv
elif k >= min and k <= max: result = isConvertible
else: result = isNone
proc handleFloatRange(f, a: PType): TTypeRelation =
@@ -159,7 +162,7 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
proc isObjectSubtype(a, f: PType): bool =
var t = a
while (t != nil) and (t.id != f.id): t = base(t)
while t != nil and t.id != f.id: t = base(t)
result = t != nil
proc minRel(a, b: TTypeRelation): TTypeRelation =
@@ -182,11 +185,15 @@ proc tupleRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
var x = f.n.sons[i].sym
var y = a.n.sons[i].sym
if x.name.id != y.name.id: return isNone
elif sonsLen(f) == 0:
idTablePut(mapping, f, a)
result = isLifted
proc constraintRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
result = isNone
if f.kind == a.kind: result = isGeneric
proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
var
x, concrete: PType
m: TTypeRelation
# is a subtype of f?
result = isNone
assert(f != nil)
@@ -272,9 +279,11 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
if result < isGeneric: result = isNone
else: nil
of tyOrdinal:
if isOrdinalType(a):
if a.kind == tyOrdinal: x = a.sons[0]
else: x = a
if f.sons[0].kind != tyGenericParam:
# some constraint:
result = constraintRel(mapping, f.sons[0], a)
elif isOrdinalType(a):
var x = if a.kind == tyOrdinal: a.sons[0] else: a
result = typeRel(mapping, f.sons[0], x)
if result < isGeneric: result = isNone
of tyForward: InternalError("forward type in typeRel()")
@@ -319,6 +328,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
# return type!
result = isEqual # start with maximum; also correct for no
# params at all
var m: TTypeRelation
for i in countup(1, sonsLen(f) - 1):
m = typeRel(mapping, f.sons[i], a.sons[i])
if (m == isNone) and
@@ -392,26 +402,25 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
if result != isNone:
# we steal the generic parameters from the tyGenericBody:
for i in countup(1, sonsLen(f) - 1):
x = PType(idTableGet(mapping, f.sons[0].sons[i - 1]))
var x = PType(idTableGet(mapping, f.sons[0].sons[i - 1]))
if (x == nil) or (x.kind == tyGenericParam):
InternalError("wrong instantiated type!")
idTablePut(mapping, f.sons[i], x)
of tyGenericParam:
x = PType(idTableGet(mapping, f))
var x = PType(idTableGet(mapping, f))
if x == nil:
if sonsLen(f) == 0:
# no constraints
concrete = concreteType(mapping, a)
var concrete = concreteType(mapping, a)
if concrete != nil:
#MessageOut('putting: ' + f.sym.name.s);
idTablePut(mapping, f, concrete)
result = isGeneric
else:
InternalError(f.sym.info, "has constraints: " & f.sym.name.s)
# check constraints:
for i in countup(0, sonsLen(f) - 1):
if typeRel(mapping, f.sons[i], a) >= isSubtype:
concrete = concreteType(mapping, a)
var concrete = concreteType(mapping, a)
if concrete != nil:
idTablePut(mapping, f, concrete)
result = isGeneric
@@ -484,6 +493,9 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
of isSubtype:
inc(m.subtypeMatches)
result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c)
of isLifted:
inc(m.genericMatches)
result = copyTree(arg)
of isGeneric:
inc(m.genericMatches)
result = copyTree(arg)