diff options
Diffstat (limited to 'rod')
-rwxr-xr-x | rod/ast.nim | 6 | ||||
-rwxr-xr-x | rod/pnimsyn.nim | 67 | ||||
-rwxr-xr-x | rod/rnimsyn.nim | 76 | ||||
-rwxr-xr-x | rod/seminst.nim | 2 | ||||
-rwxr-xr-x | rod/semstmts.nim | 171 | ||||
-rwxr-xr-x | rod/semtypes.nim | 77 | ||||
-rwxr-xr-x | rod/sigmatch.nim | 42 |
7 files changed, 320 insertions, 121 deletions
diff --git a/rod/ast.nim b/rod/ast.nim index e19192f1f..fb610f565 100755 --- a/rod/ast.nim +++ b/rod/ast.nim @@ -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, diff --git a/rod/pnimsyn.nim b/rod/pnimsyn.nim index fb2b7429e..869d968b6 100755 --- a/rod/pnimsyn.nim +++ b/rod/pnimsyn.nim @@ -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) diff --git a/rod/rnimsyn.nim b/rod/rnimsyn.nim index 2c97876b1..01d3e066c 100755 --- a/rod/rnimsyn.nim +++ b/rod/rnimsyn.nim @@ -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 & ')') diff --git a/rod/seminst.nim b/rod/seminst.nim index 2f26026ad..99fd1fb87 100755 --- a/rod/seminst.nim +++ b/rod/seminst.nim @@ -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) diff --git a/rod/semstmts.nim b/rod/semstmts.nim index 176fdad1b..b2fae3f31 100755 --- a/rod/semstmts.nim +++ b/rod/semstmts.nim @@ -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 = diff --git a/rod/semtypes.nim b/rod/semtypes.nim index 90a774645..79511b716 100755 --- a/rod/semtypes.nim +++ b/rod/semtypes.nim @@ -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) + + diff --git a/rod/sigmatch.nim b/rod/sigmatch.nim index 8144cff0b..1e61ddfe0 100755 --- a/rod/sigmatch.nim +++ b/rod/sigmatch.nim @@ -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) |