wip type class reforms (the compiler bootstraps fine)
* replace tfAny and tfAll with tyAnd and tyOr * integrate matchTypeClass into typeRel * introduce tyBuiltInTypeClass to handle types such as tuple, object, proc, etc
This commit is contained in:
parent
299cefdc98
commit
1d02f2ea53
8 changed files with 94 additions and 99 deletions
|
|
@ -339,6 +339,7 @@ type
|
||||||
tyTypeClass
|
tyTypeClass
|
||||||
tyParametricTypeClass # structured similarly to tyGenericInst
|
tyParametricTypeClass # structured similarly to tyGenericInst
|
||||||
# lastSon is the body of the type class
|
# lastSon is the body of the type class
|
||||||
|
tyBuiltInTypeClass
|
||||||
tyAnd
|
tyAnd
|
||||||
tyOr
|
tyOr
|
||||||
tyNot
|
tyNot
|
||||||
|
|
@ -349,7 +350,8 @@ const
|
||||||
tyPureObject* = tyTuple
|
tyPureObject* = tyTuple
|
||||||
GcTypeKinds* = {tyRef, tySequence, tyString}
|
GcTypeKinds* = {tyRef, tySequence, tyString}
|
||||||
tyError* = tyProxy # as an errornous node should match everything
|
tyError* = tyProxy # as an errornous node should match everything
|
||||||
tyTypeClasses* = {tyTypeClass, tyParametricTypeClass, tyAnd, tyOr, tyNot, tyAnything}
|
tyTypeClasses* = {tyTypeClass, tyBuiltInTypeClass,
|
||||||
|
tyParametricTypeClass, tyAnd, tyOr, tyNot, tyAnything}
|
||||||
|
|
||||||
type
|
type
|
||||||
TTypeKinds* = set[TTypeKind]
|
TTypeKinds* = set[TTypeKind]
|
||||||
|
|
@ -384,9 +386,6 @@ type
|
||||||
# proc foo(T: typedesc, list: seq[T]): var T
|
# proc foo(T: typedesc, list: seq[T]): var T
|
||||||
tfRetType, # marks return types in proc (used to detect type classes
|
tfRetType, # marks return types in proc (used to detect type classes
|
||||||
# used as return types for return type inference)
|
# used as return types for return type inference)
|
||||||
tfAll, # type class requires all constraints to be met (default)
|
|
||||||
tfAny, # type class requires any constraint to be met
|
|
||||||
tfNot, # type class with a negative check
|
|
||||||
tfCapturesEnv, # whether proc really captures some environment
|
tfCapturesEnv, # whether proc really captures some environment
|
||||||
tfByCopy, # pass object/tuple by copy (C backend)
|
tfByCopy, # pass object/tuple by copy (C backend)
|
||||||
tfByRef, # pass object/tuple by reference (C backend)
|
tfByRef, # pass object/tuple by reference (C backend)
|
||||||
|
|
@ -399,6 +398,7 @@ type
|
||||||
tfHasShared, # type constains a "shared" constraint modifier somewhere
|
tfHasShared, # type constains a "shared" constraint modifier somewhere
|
||||||
tfHasMeta, # type has "typedesc" or "expr" somewhere; or uses '|'
|
tfHasMeta, # type has "typedesc" or "expr" somewhere; or uses '|'
|
||||||
tfHasGCedMem, # type contains GC'ed memory
|
tfHasGCedMem, # type contains GC'ed memory
|
||||||
|
tfGenericTypeParam
|
||||||
|
|
||||||
TTypeFlags* = set[TTypeFlag]
|
TTypeFlags* = set[TTypeFlag]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -643,6 +643,8 @@ proc toFileLine*(info: TLineInfo): string {.inline.} =
|
||||||
proc toFileLineCol*(info: TLineInfo): string {.inline.} =
|
proc toFileLineCol*(info: TLineInfo): string {.inline.} =
|
||||||
result = info.toFilename & "(" & $info.line & "," & $info.col & ")"
|
result = info.toFilename & "(" & $info.line & "," & $info.col & ")"
|
||||||
|
|
||||||
|
template `$`*(info: TLineInfo): expr = toFileLineCol(info)
|
||||||
|
|
||||||
proc `??`* (info: TLineInfo, filename: string): bool =
|
proc `??`* (info: TLineInfo, filename: string): bool =
|
||||||
# only for debugging purposes
|
# only for debugging purposes
|
||||||
result = filename in info.toFilename
|
result = filename in info.toFilename
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,21 @@ proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
|
||||||
let sym = newSym(skType, idAnon, getCurrOwner(), info).linkTo(typedesc)
|
let sym = newSym(skType, idAnon, getCurrOwner(), info).linkTo(typedesc)
|
||||||
return newSymNode(sym, info)
|
return newSymNode(sym, info)
|
||||||
|
|
||||||
|
proc makeAndType*(c: PContext, t1, t2: PType): PType =
|
||||||
|
result = newTypeS(tyAnd, c)
|
||||||
|
result.sons = @[t1, t2]
|
||||||
|
result.flags.incl tfHasMeta
|
||||||
|
|
||||||
|
proc makeOrType*(c: PContext, t1, t2: PType): PType =
|
||||||
|
result = newTypeS(tyOr, c)
|
||||||
|
result.sons = @[t1, t2]
|
||||||
|
result.flags.incl tfHasMeta
|
||||||
|
|
||||||
|
proc makeNotType*(c: PContext, t1: PType): PType =
|
||||||
|
result = newTypeS(tyNot, c)
|
||||||
|
result.sons = @[t1]
|
||||||
|
result.flags.incl tfHasMeta
|
||||||
|
|
||||||
proc newTypeS(kind: TTypeKind, c: PContext): PType =
|
proc newTypeS(kind: TTypeKind, c: PContext): PType =
|
||||||
result = newType(kind, getCurrOwner())
|
result = newType(kind, getCurrOwner())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1163,7 +1163,7 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
||||||
if lhsIsResult:
|
if lhsIsResult:
|
||||||
n.typ = EnforceVoidContext
|
n.typ = EnforceVoidContext
|
||||||
if lhs.sym.typ.kind == tyGenericParam:
|
if lhs.sym.typ.kind == tyGenericParam:
|
||||||
if matchTypeClass(lhs.typ, rhs.typ):
|
if cmpTypes(c, lhs.typ, rhs.typ) == isGeneric:
|
||||||
InternalAssert c.p.resultSym != nil
|
InternalAssert c.p.resultSym != nil
|
||||||
lhs.typ = rhs.typ
|
lhs.typ = rhs.typ
|
||||||
c.p.resultSym.typ = rhs.typ
|
c.p.resultSym.typ = rhs.typ
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
|
||||||
if result.kind == tyForward: result.kind = kind
|
if result.kind == tyForward: result.kind = kind
|
||||||
|
|
||||||
proc newConstraint(c: PContext, k: TTypeKind): PType =
|
proc newConstraint(c: PContext, k: TTypeKind): PType =
|
||||||
result = newTypeS(tyTypeClass, c)
|
result = newTypeS(tyBuiltInTypeClass, c)
|
||||||
result.addSonSkipIntLit(newTypeS(k, c))
|
result.addSonSkipIntLit(newTypeS(k, c))
|
||||||
|
|
||||||
proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||||
|
|
@ -603,6 +603,10 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType =
|
proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType =
|
||||||
let finalTypId = if typId != nil: typId
|
let finalTypId = if typId != nil: typId
|
||||||
else: getIdent(paramName & ":type")
|
else: getIdent(paramName & ":type")
|
||||||
|
if genericParams == nil:
|
||||||
|
# This happens with anonymous proc types appearing in signatures
|
||||||
|
# XXX: we need to lift these earlier
|
||||||
|
return
|
||||||
# is this a bindOnce type class already present in the param list?
|
# is this a bindOnce type class already present in the param list?
|
||||||
for i in countup(0, genericParams.len - 1):
|
for i in countup(0, genericParams.len - 1):
|
||||||
if genericParams.sons[i].sym.name.id == finalTypId.id:
|
if genericParams.sons[i].sym.name.id == finalTypId.id:
|
||||||
|
|
@ -674,7 +678,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
paramType.sons[i] = lifted
|
paramType.sons[i] = lifted
|
||||||
result = paramType
|
result = paramType
|
||||||
|
|
||||||
if paramType.lastSon.kind == tyTypeClass:
|
if paramType.lastSon.kind == tyTypeClass and false:
|
||||||
result = paramType
|
result = paramType
|
||||||
result.kind = tyParametricTypeClass
|
result.kind = tyParametricTypeClass
|
||||||
result = addImplicitGeneric(copyType(result,
|
result = addImplicitGeneric(copyType(result,
|
||||||
|
|
@ -682,10 +686,16 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
elif result != nil:
|
elif result != nil:
|
||||||
result.kind = tyGenericInvokation
|
result.kind = tyGenericInvokation
|
||||||
result.sons.setLen(result.sons.len - 1)
|
result.sons.setLen(result.sons.len - 1)
|
||||||
of tyTypeClass:
|
of tyTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
|
||||||
result = addImplicitGeneric(copyType(paramType, getCurrOwner(), false))
|
result = addImplicitGeneric(copyType(paramType, getCurrOwner(), false))
|
||||||
of tyExpr:
|
of tyExpr:
|
||||||
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
|
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
|
||||||
|
of tyGenericParam:
|
||||||
|
if tfGenericTypeParam in paramType.flags and false:
|
||||||
|
if paramType.sonsLen > 0:
|
||||||
|
result = liftingWalk(paramType.lastSon)
|
||||||
|
else:
|
||||||
|
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
# result = liftingWalk(paramType)
|
# result = liftingWalk(paramType)
|
||||||
|
|
@ -924,19 +934,22 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
LocalError(n.sons[2].info, errTypeExpected)
|
LocalError(n.sons[2].info, errTypeExpected)
|
||||||
result = newOrPrevType(tyError, prev, c)
|
result = newOrPrevType(tyError, prev, c)
|
||||||
else:
|
else:
|
||||||
result = newTypeS(tyTypeClass, c)
|
result = if op.id == ord(wAnd): makeAndType(c, t1, t2)
|
||||||
result.addSonSkipIntLit(t1)
|
else: makeOrType(c, t1, t2)
|
||||||
result.addSonSkipIntLit(t2)
|
|
||||||
result.flags.incl(if op.id == ord(wAnd): tfAll else: tfAny)
|
|
||||||
result.flags.incl(tfHasMeta)
|
|
||||||
elif op.id == ord(wNot):
|
elif op.id == ord(wNot):
|
||||||
checkSonsLen(n, 3)
|
case n.len
|
||||||
|
of 3:
|
||||||
result = semTypeNode(c, n.sons[1], prev)
|
result = semTypeNode(c, n.sons[1], prev)
|
||||||
if result.kind in NilableTypes and n.sons[2].kind == nkNilLit:
|
if result.kind in NilableTypes and n.sons[2].kind == nkNilLit:
|
||||||
result = freshType(result, prev)
|
result = freshType(result, prev)
|
||||||
result.flags.incl(tfNotNil)
|
result.flags.incl(tfNotNil)
|
||||||
else:
|
else:
|
||||||
LocalError(n.info, errGenerated, "invalid type")
|
LocalError(n.info, errGenerated, "invalid type")
|
||||||
|
of 2:
|
||||||
|
let negated = semTypeNode(c, n.sons[1], prev)
|
||||||
|
result = makeNotType(c, negated)
|
||||||
|
else:
|
||||||
|
LocalError(n.info, errGenerated, "invalid type")
|
||||||
else:
|
else:
|
||||||
result = semTypeExpr(c, n)
|
result = semTypeExpr(c, n)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1088,10 +1101,6 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||||
else: LocalError(m.info, errTypeExpected)
|
else: LocalError(m.info, errTypeExpected)
|
||||||
|
|
||||||
proc semGenericConstraints(c: PContext, x: PType): PType =
|
proc semGenericConstraints(c: PContext, x: PType): PType =
|
||||||
if x.kind in StructuralEquivTypes and (
|
|
||||||
sonsLen(x) == 0 or x.sons[0].kind in {tyGenericParam, tyEmpty}):
|
|
||||||
result = newConstraint(c, x.kind)
|
|
||||||
else:
|
|
||||||
result = newTypeWithSons(c, tyGenericParam, @[x])
|
result = newTypeWithSons(c, tyGenericParam, @[x])
|
||||||
|
|
||||||
proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||||
|
|
@ -1128,6 +1137,8 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||||
if typ == nil:
|
if typ == nil:
|
||||||
typ = newTypeS(tyGenericParam, c)
|
typ = newTypeS(tyGenericParam, c)
|
||||||
|
|
||||||
|
typ.flags.incl tfGenericTypeParam
|
||||||
|
|
||||||
for j in countup(0, L-3):
|
for j in countup(0, L-3):
|
||||||
let finalType = if j == 0: typ
|
let finalType = if j == 0: typ
|
||||||
else: copyType(typ, typ.owner, false)
|
else: copyType(typ, typ.owner, false)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ proc checkPartialConstructedType(info: TLineInfo, t: PType) =
|
||||||
|
|
||||||
proc checkConstructedType*(info: TLineInfo, typ: PType) =
|
proc checkConstructedType*(info: TLineInfo, typ: PType) =
|
||||||
var t = typ.skipTypes({tyDistinct})
|
var t = typ.skipTypes({tyDistinct})
|
||||||
if t.kind in {tyTypeClass}: nil
|
if t.kind in tyTypeClasses: nil
|
||||||
elif tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
|
elif tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
|
||||||
LocalError(info, errInvalidPragmaX, "acyclic")
|
LocalError(info, errInvalidPragmaX, "acyclic")
|
||||||
elif t.kind == tyVar and t.sons[0].kind == tyVar:
|
elif t.kind == tyVar and t.sons[0].kind == tyVar:
|
||||||
|
|
|
||||||
|
|
@ -370,10 +370,6 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
of tyNil: result = f.allowsNil
|
of tyNil: result = f.allowsNil
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
proc matchTypeClass(c: var TCandidate, f, a: PType): TTypeRelation =
|
|
||||||
result = if matchTypeClass(c.bindings, f, a): isGeneric
|
|
||||||
else: isNone
|
|
||||||
|
|
||||||
proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
|
proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
|
||||||
let
|
let
|
||||||
a0 = firstOrd(a)
|
a0 = firstOrd(a)
|
||||||
|
|
@ -707,6 +703,19 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
|
||||||
else:
|
else:
|
||||||
return typeRel(c, prev, a)
|
return typeRel(c, prev, a)
|
||||||
|
|
||||||
|
of tyBuiltInTypeClass:
|
||||||
|
var prev = PType(idTableGet(c.bindings, f))
|
||||||
|
if prev == nil:
|
||||||
|
let targetKind = f.sons[0].kind
|
||||||
|
if targetKind == a.skipTypes({tyRange}).kind or
|
||||||
|
(targetKind in {tyProc, tyPointer} and a.kind == tyNil):
|
||||||
|
put(c.bindings, f, a)
|
||||||
|
return isGeneric
|
||||||
|
else:
|
||||||
|
return isNone
|
||||||
|
else:
|
||||||
|
result = typeRel(c, prev, a)
|
||||||
|
|
||||||
of tyGenericParam, tyTypeClass:
|
of tyGenericParam, tyTypeClass:
|
||||||
var x = PType(idTableGet(c.bindings, f))
|
var x = PType(idTableGet(c.bindings, f))
|
||||||
if x == nil:
|
if x == nil:
|
||||||
|
|
@ -727,10 +736,10 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
|
||||||
else:
|
else:
|
||||||
result = isNone
|
result = isNone
|
||||||
else:
|
else:
|
||||||
if a.kind == tyTypeClass:
|
if f.sonsLen > 0:
|
||||||
result = isGeneric
|
result = typeRel(c, f.lastSon, a)
|
||||||
else:
|
else:
|
||||||
result = matchTypeClass(c, f, a)
|
result = isGeneric
|
||||||
|
|
||||||
if result == isGeneric:
|
if result == isGeneric:
|
||||||
var concrete = concreteType(c, a)
|
var concrete = concreteType(c, a)
|
||||||
|
|
@ -751,7 +760,7 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
|
||||||
if f.sonsLen == 0:
|
if f.sonsLen == 0:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
else:
|
else:
|
||||||
result = matchTypeClass(c, f, a.sons[0])
|
result = typeRel(c, f, a.sons[0])
|
||||||
if result == isGeneric:
|
if result == isGeneric:
|
||||||
put(c.bindings, f, a)
|
put(c.bindings, f, a)
|
||||||
else:
|
else:
|
||||||
|
|
@ -911,9 +920,8 @@ proc ParamTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
InternalAssert a.len > 0
|
InternalAssert a.len > 0
|
||||||
r = typeRel(m, f.lastSon, a.lastSon)
|
r = typeRel(m, f.lastSon, a.lastSon)
|
||||||
else:
|
else:
|
||||||
let match = matchTypeClass(m.bindings, fMaybeStatic, a)
|
r = typeRel(m, fMaybeStatic, a)
|
||||||
if not match: r = isNone
|
if r != isNone:
|
||||||
else:
|
|
||||||
# XXX: Ideally, this should happen much earlier somewhere near
|
# XXX: Ideally, this should happen much earlier somewhere near
|
||||||
# semOpAux, but to do that, we need to be able to query the
|
# semOpAux, but to do that, we need to be able to query the
|
||||||
# overload set to determine whether compile-time value is expected
|
# overload set to determine whether compile-time value is expected
|
||||||
|
|
|
||||||
|
|
@ -409,18 +409,8 @@ const
|
||||||
"uint", "uint8", "uint16", "uint32", "uint64",
|
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||||
"bignum", "const ",
|
"bignum", "const ",
|
||||||
"!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass",
|
"!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass",
|
||||||
"ParametricTypeClass", "and", "or", "not", "any", "static"]
|
"ParametricTypeClass", "BuiltInTypeClass",
|
||||||
|
"and", "or", "not", "any", "static"]
|
||||||
proc consToStr(t: PType): string =
|
|
||||||
if t.len > 0: result = t.typeToString
|
|
||||||
else: result = typeToStr[t.kind].strip
|
|
||||||
|
|
||||||
proc constraintsToStr(t: PType): string =
|
|
||||||
let sep = if tfAny in t.flags: " or " else: " and "
|
|
||||||
result = ""
|
|
||||||
for i in countup(0, t.len - 1):
|
|
||||||
if i > 0: result.add(sep)
|
|
||||||
result.add(t.sons[i].consToStr)
|
|
||||||
|
|
||||||
proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
var t = typ
|
var t = typ
|
||||||
|
|
@ -444,19 +434,24 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
add(result, ']')
|
add(result, ']')
|
||||||
of tyTypeDesc:
|
of tyTypeDesc:
|
||||||
if t.len == 0: result = "typedesc"
|
if t.len == 0: result = "typedesc"
|
||||||
else: result = "typedesc[" & constraintsToStr(t) & "]"
|
else: result = "typedesc[" & typeToString(t) & "]"
|
||||||
of tyStatic:
|
of tyStatic:
|
||||||
InternalAssert t.len > 0
|
InternalAssert t.len > 0
|
||||||
result = "static[" & constraintsToStr(t) & "]"
|
result = "static[" & typeToString(t) & "]"
|
||||||
of tyTypeClass:
|
of tyTypeClass:
|
||||||
if t.n != nil: return t.sym.owner.name.s
|
InternalAssert t.sym != nil and t.sym.owner != nil
|
||||||
case t.len
|
return t.sym.owner.name.s
|
||||||
of 0: result = "typeclass[]"
|
of tyBuiltInTypeClass:
|
||||||
of 1: result = "typeclass[" & consToStr(t.sons[0]) & "]"
|
return "TypeClass"
|
||||||
else: result = constraintsToStr(t)
|
of tyAnd:
|
||||||
|
result = typeToString(t.sons[0]) & " and " & typeToString(t.sons[1])
|
||||||
|
of tyOr:
|
||||||
|
result = typeToString(t.sons[0]) & " and " & typeToString(t.sons[1])
|
||||||
|
of tyNot:
|
||||||
|
result = "not " & typeToString(t.sons[0])
|
||||||
of tyExpr:
|
of tyExpr:
|
||||||
if t.len == 0: result = "expr"
|
if t.len == 0: result = "expr"
|
||||||
else: result = "expr[" & constraintsToStr(t) & "]"
|
else: result = "expr[" & typeToString(t) & "]"
|
||||||
of tyArray:
|
of tyArray:
|
||||||
if t.sons[0].kind == tyRange:
|
if t.sons[0].kind == tyRange:
|
||||||
result = "array[" & rangeToStr(t.sons[0].n) & ", " &
|
result = "array[" & rangeToStr(t.sons[0].n) & ", " &
|
||||||
|
|
@ -978,42 +973,6 @@ proc isGenericAlias*(t: PType): bool =
|
||||||
proc skipGenericAlias*(t: PType): PType =
|
proc skipGenericAlias*(t: PType): PType =
|
||||||
return if t.isGenericAlias: t.lastSon else: t
|
return if t.isGenericAlias: t.lastSon else: t
|
||||||
|
|
||||||
proc matchTypeClass*(bindings: var TIdTable, typeClass, t: PType): bool =
|
|
||||||
for i in countup(0, typeClass.sonsLen - 1):
|
|
||||||
let req = typeClass.sons[i]
|
|
||||||
var match = req.kind == skipTypes(t, {tyRange, tyGenericInst}).kind
|
|
||||||
|
|
||||||
if not match:
|
|
||||||
case req.kind
|
|
||||||
of tyGenericBody:
|
|
||||||
if t.kind == tyGenericInst and t.sons[0] == req:
|
|
||||||
match = true
|
|
||||||
IdTablePut(bindings, typeClass, t)
|
|
||||||
of tyTypeClass:
|
|
||||||
match = matchTypeClass(bindings, req, t)
|
|
||||||
elif t.kind == tyTypeClass:
|
|
||||||
match = matchTypeClass(bindings, t, req)
|
|
||||||
|
|
||||||
elif t.kind in {tyObject} and req.len != 0:
|
|
||||||
# empty 'object' is fine as constraint in a type class
|
|
||||||
match = sameType(t, req)
|
|
||||||
|
|
||||||
if tfAny in typeClass.flags:
|
|
||||||
if match: return true
|
|
||||||
else:
|
|
||||||
if not match: return false
|
|
||||||
|
|
||||||
# if the loop finished without returning, either all constraints matched
|
|
||||||
# or none of them matched.
|
|
||||||
result = if tfAny in typeClass.flags: false else: true
|
|
||||||
if result == true:
|
|
||||||
IdTablePut(bindings, typeClass, t)
|
|
||||||
|
|
||||||
proc matchTypeClass*(typeClass, typ: PType): bool =
|
|
||||||
var bindings: TIdTable
|
|
||||||
initIdTable(bindings)
|
|
||||||
result = matchTypeClass(bindings, typeClass, typ)
|
|
||||||
|
|
||||||
proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
|
proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
|
||||||
flags: TTypeAllowedFlags = {}): bool =
|
flags: TTypeAllowedFlags = {}): bool =
|
||||||
assert(kind in {skVar, skLet, skConst, skParam, skResult})
|
assert(kind in {skVar, skLet, skConst, skParam, skResult})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue