* nested typeToString * typeToString: preferResolved * add test * fix test * preferMixed * fix tests
This commit is contained in:
parent
f9600b7207
commit
9ae0dd611f
6 changed files with 272 additions and 203 deletions
|
|
@ -141,6 +141,14 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
|
||||||
return typeWithSonsResult(tyAnd, @[operand, operand2])
|
return typeWithSonsResult(tyAnd, @[operand, operand2])
|
||||||
of "not":
|
of "not":
|
||||||
return typeWithSonsResult(tyNot, @[operand])
|
return typeWithSonsResult(tyNot, @[operand])
|
||||||
|
of "typeToString":
|
||||||
|
var prefer = preferTypeName
|
||||||
|
if traitCall.sons.len >= 2:
|
||||||
|
let preferStr = traitCall.sons[2].strVal
|
||||||
|
prefer = parseEnum[TPreferedDesc](preferStr)
|
||||||
|
result = newStrNode(nkStrLit, operand.typeToString(prefer))
|
||||||
|
result.typ = newType(tyString, context)
|
||||||
|
result.info = traitCall.info
|
||||||
of "name", "$":
|
of "name", "$":
|
||||||
result = newStrNode(nkStrLit, operand.typeToString(preferTypeName))
|
result = newStrNode(nkStrLit, operand.typeToString(preferTypeName))
|
||||||
result.typ = newType(tyString, context)
|
result.typ = newType(tyString, context)
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,14 @@ import
|
||||||
|
|
||||||
type
|
type
|
||||||
TPreferedDesc* = enum
|
TPreferedDesc* = enum
|
||||||
preferName, preferDesc, preferExported, preferModuleInfo, preferGenericArg,
|
preferName, # default
|
||||||
preferTypeName
|
preferDesc, # probably should become what preferResolved is
|
||||||
|
preferExported,
|
||||||
|
preferModuleInfo, # fully qualified
|
||||||
|
preferGenericArg,
|
||||||
|
preferTypeName,
|
||||||
|
preferResolved, # fully resolved symbols
|
||||||
|
preferMixed, # show symbol + resolved symbols if it differs, eg: seq[cint{int32}, float]
|
||||||
|
|
||||||
proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
|
proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
|
||||||
template `$`*(typ: PType): string = typeToString(typ)
|
template `$`*(typ: PType): string = typeToString(typ)
|
||||||
|
|
@ -121,6 +127,7 @@ proc isFloatLit*(t: PType): bool {.inline.} =
|
||||||
|
|
||||||
proc getProcHeader*(conf: ConfigRef; sym: PSym; prefer: TPreferedDesc = preferName; getDeclarationPath = true): string =
|
proc getProcHeader*(conf: ConfigRef; sym: PSym; prefer: TPreferedDesc = preferName; getDeclarationPath = true): string =
|
||||||
assert sym != nil
|
assert sym != nil
|
||||||
|
# consider using `skipGenericOwner` to avoid fun2.fun2 when fun2 is generic
|
||||||
result = sym.owner.name.s & '.' & sym.name.s
|
result = sym.owner.name.s & '.' & sym.name.s
|
||||||
if sym.kind in routineKinds:
|
if sym.kind in routineKinds:
|
||||||
result.add '('
|
result.add '('
|
||||||
|
|
@ -415,12 +422,12 @@ proc rangeToStr(n: PNode): string =
|
||||||
result = valueToString(n.sons[0]) & ".." & valueToString(n.sons[1])
|
result = valueToString(n.sons[0]) & ".." & valueToString(n.sons[1])
|
||||||
|
|
||||||
const
|
const
|
||||||
typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
|
typeToStr: array[TTypeKind, string] = ["None", "bool", "char", "empty",
|
||||||
"Alias", "nil", "untyped", "typed", "typeDesc",
|
"Alias", "nil", "untyped", "typed", "typeDesc",
|
||||||
"GenericInvocation", "GenericBody", "GenericInst", "GenericParam",
|
"GenericInvocation", "GenericBody", "GenericInst", "GenericParam",
|
||||||
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
|
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
|
||||||
"set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
|
"set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
|
||||||
"pointer", "OpenArray[$1]", "string", "CString", "Forward",
|
"pointer", "OpenArray[$1]", "string", "cstring", "Forward",
|
||||||
"int", "int8", "int16", "int32", "int64",
|
"int", "int8", "int16", "int32", "int64",
|
||||||
"float", "float32", "float64", "float128",
|
"float", "float32", "float64", "float128",
|
||||||
"uint", "uint8", "uint16", "uint32", "uint64",
|
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||||
|
|
@ -431,7 +438,8 @@ const
|
||||||
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor",
|
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor",
|
||||||
"void"]
|
"void"]
|
||||||
|
|
||||||
const preferToResolveSymbols = {preferName, preferTypeName, preferModuleInfo, preferGenericArg}
|
const preferToResolveSymbols = {preferName, preferTypeName, preferModuleInfo,
|
||||||
|
preferGenericArg, preferResolved, preferMixed}
|
||||||
|
|
||||||
template bindConcreteTypeToUserTypeClass*(tc, concrete: PType) =
|
template bindConcreteTypeToUserTypeClass*(tc, concrete: PType) =
|
||||||
tc.sons.add concrete
|
tc.sons.add concrete
|
||||||
|
|
@ -450,208 +458,232 @@ proc addTypeFlags(name: var string, typ: PType) {.inline.} =
|
||||||
if tfNotNil in typ.flags: name.add(" not nil")
|
if tfNotNil in typ.flags: name.add(" not nil")
|
||||||
|
|
||||||
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
var t = typ
|
let preferToplevel = prefer
|
||||||
result = ""
|
proc getPrefer(prefer: TPreferedDesc): TPreferedDesc =
|
||||||
if t == nil: return
|
if preferToplevel in {preferResolved, preferMixed}:
|
||||||
if prefer in preferToResolveSymbols and t.sym != nil and
|
preferToplevel # sticky option
|
||||||
sfAnon notin t.sym.flags and t.kind != tySequence:
|
|
||||||
if t.kind == tyInt and isIntLit(t):
|
|
||||||
result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
|
|
||||||
elif t.kind == tyAlias and t.sons[0].kind != tyAlias:
|
|
||||||
result = typeToString(t.sons[0])
|
|
||||||
elif prefer in {preferName, preferTypeName} or t.sym.owner.isNil:
|
|
||||||
result = t.sym.name.s
|
|
||||||
if t.kind == tyGenericParam and t.sonsLen > 0:
|
|
||||||
result.add ": "
|
|
||||||
var first = true
|
|
||||||
for son in t.sons:
|
|
||||||
if not first: result.add " or "
|
|
||||||
result.add son.typeToString
|
|
||||||
first = false
|
|
||||||
else:
|
else:
|
||||||
result = t.sym.owner.name.s & '.' & t.sym.name.s
|
prefer
|
||||||
result.addTypeFlags(t)
|
|
||||||
return
|
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
case t.kind
|
let prefer = getPrefer(prefer)
|
||||||
of tyInt:
|
let t = typ
|
||||||
if not isIntLit(t) or prefer == preferExported:
|
result = ""
|
||||||
result = typeToStr[t.kind]
|
if t == nil: return
|
||||||
else:
|
if prefer in preferToResolveSymbols and t.sym != nil and
|
||||||
if prefer == preferGenericArg:
|
sfAnon notin t.sym.flags and t.kind != tySequence:
|
||||||
result = $t.n.intVal
|
if t.kind == tyInt and isIntLit(t):
|
||||||
|
result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
|
||||||
|
elif t.kind == tyAlias and t.sons[0].kind != tyAlias:
|
||||||
|
result = typeToString(t.sons[0])
|
||||||
|
elif prefer in {preferResolved, preferMixed}:
|
||||||
|
case t.kind
|
||||||
|
of IntegralTypes + {tyFloat..tyFloat128} + {tyString, tyCString}:
|
||||||
|
result = typeToStr[t.kind]
|
||||||
|
of tyGenericBody:
|
||||||
|
result = typeToString(t.lastSon)
|
||||||
|
of tyCompositeTypeClass:
|
||||||
|
# avoids showing `A[any]` in `proc fun(a: A)` with `A = object[T]`
|
||||||
|
result = typeToString(t.lastSon.lastSon)
|
||||||
|
else:
|
||||||
|
result = t.sym.name.s
|
||||||
|
if prefer == preferMixed and result != t.sym.name.s:
|
||||||
|
result = t.sym.name.s & "{" & result & "}"
|
||||||
|
elif prefer in {preferName, preferTypeName} or t.sym.owner.isNil:
|
||||||
|
# note: should probably be: {preferName, preferTypeName, preferGenericArg}
|
||||||
|
result = t.sym.name.s
|
||||||
|
if t.kind == tyGenericParam and t.sonsLen > 0:
|
||||||
|
result.add ": "
|
||||||
|
var first = true
|
||||||
|
for son in t.sons:
|
||||||
|
if not first: result.add " or "
|
||||||
|
result.add son.typeToString
|
||||||
|
first = false
|
||||||
else:
|
else:
|
||||||
result = "int literal(" & $t.n.intVal & ")"
|
result = t.sym.owner.name.s & '.' & t.sym.name.s
|
||||||
of tyGenericInst, tyGenericInvocation:
|
result.addTypeFlags(t)
|
||||||
result = typeToString(t.sons[0]) & '['
|
return
|
||||||
for i in 1 ..< sonsLen(t)-ord(t.kind != tyGenericInvocation):
|
case t.kind
|
||||||
if i > 1: add(result, ", ")
|
of tyInt:
|
||||||
add(result, typeToString(t.sons[i], preferGenericArg))
|
if not isIntLit(t) or prefer == preferExported:
|
||||||
add(result, ']')
|
result = typeToStr[t.kind]
|
||||||
of tyGenericBody:
|
else:
|
||||||
result = typeToString(t.lastSon) & '['
|
if prefer == preferGenericArg:
|
||||||
for i in 0 .. sonsLen(t)-2:
|
result = $t.n.intVal
|
||||||
if i > 0: add(result, ", ")
|
else:
|
||||||
add(result, typeToString(t.sons[i], preferTypeName))
|
result = "int literal(" & $t.n.intVal & ")"
|
||||||
add(result, ']')
|
of tyGenericInst, tyGenericInvocation:
|
||||||
of tyTypeDesc:
|
result = typeToString(t.sons[0]) & '['
|
||||||
if t.sons[0].kind == tyNone: result = "typedesc"
|
for i in 1 ..< sonsLen(t)-ord(t.kind != tyGenericInvocation):
|
||||||
else: result = "type " & typeToString(t.sons[0])
|
if i > 1: add(result, ", ")
|
||||||
of tyStatic:
|
add(result, typeToString(t.sons[i], preferGenericArg))
|
||||||
if prefer == preferGenericArg and t.n != nil:
|
|
||||||
result = t.n.renderTree
|
|
||||||
else:
|
|
||||||
result = "static[" & (if t.len > 0: typeToString(t.sons[0]) else: "") & "]"
|
|
||||||
if t.n != nil: result.add "(" & renderTree(t.n) & ")"
|
|
||||||
of tyUserTypeClass:
|
|
||||||
if t.sym != nil and t.sym.owner != nil:
|
|
||||||
if t.isResolvedUserTypeClass: return typeToString(t.lastSon)
|
|
||||||
return t.sym.owner.name.s
|
|
||||||
else:
|
|
||||||
result = "<invalid tyUserTypeClass>"
|
|
||||||
of tyBuiltInTypeClass:
|
|
||||||
result = case t.base.kind:
|
|
||||||
of tyVar: "var"
|
|
||||||
of tyRef: "ref"
|
|
||||||
of tyPtr: "ptr"
|
|
||||||
of tySequence: "seq"
|
|
||||||
of tyArray: "array"
|
|
||||||
of tySet: "set"
|
|
||||||
of tyRange: "range"
|
|
||||||
of tyDistinct: "distinct"
|
|
||||||
of tyProc: "proc"
|
|
||||||
of tyObject: "object"
|
|
||||||
of tyTuple: "tuple"
|
|
||||||
of tyOpenArray: "openarray"
|
|
||||||
else: typeToStr[t.base.kind]
|
|
||||||
of tyInferred:
|
|
||||||
let concrete = t.previouslyInferred
|
|
||||||
if concrete != nil: result = typeToString(concrete)
|
|
||||||
else: result = "inferred[" & typeToString(t.base) & "]"
|
|
||||||
of tyUserTypeClassInst:
|
|
||||||
let body = t.base
|
|
||||||
result = body.sym.name.s & "["
|
|
||||||
for i in 1 .. sonsLen(t) - 2:
|
|
||||||
if i > 1: add(result, ", ")
|
|
||||||
add(result, typeToString(t.sons[i]))
|
|
||||||
result.add "]"
|
|
||||||
of tyAnd:
|
|
||||||
for i, son in t.sons:
|
|
||||||
result.add(typeToString(son))
|
|
||||||
if i < t.sons.high:
|
|
||||||
result.add(" and ")
|
|
||||||
of tyOr:
|
|
||||||
for i, son in t.sons:
|
|
||||||
result.add(typeToString(son))
|
|
||||||
if i < t.sons.high:
|
|
||||||
result.add(" or ")
|
|
||||||
of tyNot:
|
|
||||||
result = "not " & typeToString(t.sons[0])
|
|
||||||
of tyUntyped:
|
|
||||||
#internalAssert t.len == 0
|
|
||||||
result = "untyped"
|
|
||||||
of tyFromExpr:
|
|
||||||
if t.n == nil:
|
|
||||||
result = "unknown"
|
|
||||||
else:
|
|
||||||
result = "type(" & renderTree(t.n) & ")"
|
|
||||||
of tyArray:
|
|
||||||
if t.sons[0].kind == tyRange:
|
|
||||||
result = "array[" & rangeToStr(t.sons[0].n) & ", " &
|
|
||||||
typeToString(t.sons[1]) & ']'
|
|
||||||
else:
|
|
||||||
result = "array[" & typeToString(t.sons[0]) & ", " &
|
|
||||||
typeToString(t.sons[1]) & ']'
|
|
||||||
of tyUncheckedArray:
|
|
||||||
result = "UncheckedArray[" & typeToString(t.sons[0]) & ']'
|
|
||||||
of tySequence:
|
|
||||||
result = "seq[" & typeToString(t.sons[0]) & ']'
|
|
||||||
of tyOpt:
|
|
||||||
result = "opt[" & typeToString(t.sons[0]) & ']'
|
|
||||||
of tyOrdinal:
|
|
||||||
result = "ordinal[" & typeToString(t.sons[0]) & ']'
|
|
||||||
of tySet:
|
|
||||||
result = "set[" & typeToString(t.sons[0]) & ']'
|
|
||||||
of tyOpenArray:
|
|
||||||
result = "openarray[" & typeToString(t.sons[0]) & ']'
|
|
||||||
of tyDistinct:
|
|
||||||
result = "distinct " & typeToString(t.sons[0],
|
|
||||||
if prefer == preferModuleInfo: preferModuleInfo else: preferTypeName)
|
|
||||||
of tyTuple:
|
|
||||||
# we iterate over t.sons here, because t.n may be nil
|
|
||||||
if t.n != nil:
|
|
||||||
result = "tuple["
|
|
||||||
assert(sonsLen(t.n) == sonsLen(t))
|
|
||||||
for i in 0 ..< sonsLen(t.n):
|
|
||||||
assert(t.n.sons[i].kind == nkSym)
|
|
||||||
add(result, t.n.sons[i].sym.name.s & ": " & typeToString(t.sons[i]))
|
|
||||||
if i < sonsLen(t.n) - 1: add(result, ", ")
|
|
||||||
add(result, ']')
|
add(result, ']')
|
||||||
elif sonsLen(t) == 0:
|
of tyGenericBody:
|
||||||
result = "tuple[]"
|
result = typeToString(t.lastSon) & '['
|
||||||
else:
|
for i in 0 .. sonsLen(t)-2:
|
||||||
if prefer == preferTypeName: result = "("
|
if i > 0: add(result, ", ")
|
||||||
else: result = "tuple of ("
|
add(result, typeToString(t.sons[i], preferTypeName))
|
||||||
for i in 0 ..< sonsLen(t):
|
add(result, ']')
|
||||||
|
of tyTypeDesc:
|
||||||
|
if t.sons[0].kind == tyNone: result = "typedesc"
|
||||||
|
else: result = "type " & typeToString(t.sons[0])
|
||||||
|
of tyStatic:
|
||||||
|
if prefer == preferGenericArg and t.n != nil:
|
||||||
|
result = t.n.renderTree
|
||||||
|
else:
|
||||||
|
result = "static[" & (if t.len > 0: typeToString(t.sons[0]) else: "") & "]"
|
||||||
|
if t.n != nil: result.add "(" & renderTree(t.n) & ")"
|
||||||
|
of tyUserTypeClass:
|
||||||
|
if t.sym != nil and t.sym.owner != nil:
|
||||||
|
if t.isResolvedUserTypeClass: return typeToString(t.lastSon)
|
||||||
|
return t.sym.owner.name.s
|
||||||
|
else:
|
||||||
|
result = "<invalid tyUserTypeClass>"
|
||||||
|
of tyBuiltInTypeClass:
|
||||||
|
result = case t.base.kind:
|
||||||
|
of tyVar: "var"
|
||||||
|
of tyRef: "ref"
|
||||||
|
of tyPtr: "ptr"
|
||||||
|
of tySequence: "seq"
|
||||||
|
of tyArray: "array"
|
||||||
|
of tySet: "set"
|
||||||
|
of tyRange: "range"
|
||||||
|
of tyDistinct: "distinct"
|
||||||
|
of tyProc: "proc"
|
||||||
|
of tyObject: "object"
|
||||||
|
of tyTuple: "tuple"
|
||||||
|
of tyOpenArray: "openArray"
|
||||||
|
else: typeToStr[t.base.kind]
|
||||||
|
of tyInferred:
|
||||||
|
let concrete = t.previouslyInferred
|
||||||
|
if concrete != nil: result = typeToString(concrete)
|
||||||
|
else: result = "inferred[" & typeToString(t.base) & "]"
|
||||||
|
of tyUserTypeClassInst:
|
||||||
|
let body = t.base
|
||||||
|
result = body.sym.name.s & "["
|
||||||
|
for i in 1 .. sonsLen(t) - 2:
|
||||||
|
if i > 1: add(result, ", ")
|
||||||
|
add(result, typeToString(t.sons[i]))
|
||||||
|
result.add "]"
|
||||||
|
of tyAnd:
|
||||||
|
for i, son in t.sons:
|
||||||
|
result.add(typeToString(son))
|
||||||
|
if i < t.sons.high:
|
||||||
|
result.add(" and ")
|
||||||
|
of tyOr:
|
||||||
|
for i, son in t.sons:
|
||||||
|
result.add(typeToString(son))
|
||||||
|
if i < t.sons.high:
|
||||||
|
result.add(" or ")
|
||||||
|
of tyNot:
|
||||||
|
result = "not " & typeToString(t.sons[0])
|
||||||
|
of tyUntyped:
|
||||||
|
#internalAssert t.len == 0
|
||||||
|
result = "untyped"
|
||||||
|
of tyFromExpr:
|
||||||
|
if t.n == nil:
|
||||||
|
result = "unknown"
|
||||||
|
else:
|
||||||
|
result = "type(" & renderTree(t.n) & ")"
|
||||||
|
of tyArray:
|
||||||
|
if t.sons[0].kind == tyRange:
|
||||||
|
result = "array[" & rangeToStr(t.sons[0].n) & ", " &
|
||||||
|
typeToString(t.sons[1]) & ']'
|
||||||
|
else:
|
||||||
|
result = "array[" & typeToString(t.sons[0]) & ", " &
|
||||||
|
typeToString(t.sons[1]) & ']'
|
||||||
|
of tyUncheckedArray:
|
||||||
|
result = "UncheckedArray[" & typeToString(t.sons[0]) & ']'
|
||||||
|
of tySequence:
|
||||||
|
result = "seq[" & typeToString(t.sons[0]) & ']'
|
||||||
|
of tyOpt:
|
||||||
|
result = "opt[" & typeToString(t.sons[0]) & ']'
|
||||||
|
of tyOrdinal:
|
||||||
|
result = "ordinal[" & typeToString(t.sons[0]) & ']'
|
||||||
|
of tySet:
|
||||||
|
result = "set[" & typeToString(t.sons[0]) & ']'
|
||||||
|
of tyOpenArray:
|
||||||
|
result = "openArray[" & typeToString(t.sons[0]) & ']'
|
||||||
|
of tyDistinct:
|
||||||
|
result = "distinct " & typeToString(t.sons[0],
|
||||||
|
if prefer == preferModuleInfo: preferModuleInfo else: preferTypeName)
|
||||||
|
of tyTuple:
|
||||||
|
# we iterate over t.sons here, because t.n may be nil
|
||||||
|
if t.n != nil:
|
||||||
|
result = "tuple["
|
||||||
|
assert(sonsLen(t.n) == sonsLen(t))
|
||||||
|
for i in 0 ..< sonsLen(t.n):
|
||||||
|
assert(t.n.sons[i].kind == nkSym)
|
||||||
|
add(result, t.n.sons[i].sym.name.s & ": " & typeToString(t.sons[i]))
|
||||||
|
if i < sonsLen(t.n) - 1: add(result, ", ")
|
||||||
|
add(result, ']')
|
||||||
|
elif sonsLen(t) == 0:
|
||||||
|
result = "tuple[]"
|
||||||
|
else:
|
||||||
|
if prefer == preferTypeName: result = "("
|
||||||
|
else: result = "tuple of ("
|
||||||
|
for i in 0 ..< sonsLen(t):
|
||||||
|
add(result, typeToString(t.sons[i]))
|
||||||
|
if i < sonsLen(t) - 1: add(result, ", ")
|
||||||
|
add(result, ')')
|
||||||
|
of tyPtr, tyRef, tyVar, tyLent:
|
||||||
|
result = typeToStr[t.kind]
|
||||||
|
if t.len >= 2:
|
||||||
|
setLen(result, result.len-1)
|
||||||
|
result.add '['
|
||||||
|
for i in 0 ..< sonsLen(t):
|
||||||
|
add(result, typeToString(t.sons[i]))
|
||||||
|
if i < sonsLen(t) - 1: add(result, ", ")
|
||||||
|
result.add ']'
|
||||||
|
else:
|
||||||
|
result.add typeToString(t.sons[0])
|
||||||
|
of tyRange:
|
||||||
|
result = "range "
|
||||||
|
if t.n != nil and t.n.kind == nkRange:
|
||||||
|
result.add rangeToStr(t.n)
|
||||||
|
if prefer != preferExported:
|
||||||
|
result.add("(" & typeToString(t.sons[0]) & ")")
|
||||||
|
of tyProc:
|
||||||
|
result = if tfIterator in t.flags: "iterator "
|
||||||
|
elif t.owner != nil:
|
||||||
|
case t.owner.kind
|
||||||
|
of skTemplate: "template "
|
||||||
|
of skMacro: "macro "
|
||||||
|
of skConverter: "converter "
|
||||||
|
else: "proc "
|
||||||
|
else:
|
||||||
|
"proc "
|
||||||
|
if tfUnresolved in t.flags: result.add "[*missing parameters*]"
|
||||||
|
result.add "("
|
||||||
|
for i in 1 ..< sonsLen(t):
|
||||||
|
if t.n != nil and i < t.n.len and t.n[i].kind == nkSym:
|
||||||
|
add(result, t.n[i].sym.name.s)
|
||||||
|
add(result, ": ")
|
||||||
add(result, typeToString(t.sons[i]))
|
add(result, typeToString(t.sons[i]))
|
||||||
if i < sonsLen(t) - 1: add(result, ", ")
|
if i < sonsLen(t) - 1: add(result, ", ")
|
||||||
add(result, ')')
|
add(result, ')')
|
||||||
of tyPtr, tyRef, tyVar, tyLent:
|
if t.len > 0 and t.sons[0] != nil: add(result, ": " & typeToString(t.sons[0]))
|
||||||
result = typeToStr[t.kind]
|
var prag = if t.callConv == ccDefault: "" else: CallingConvToStr[t.callConv]
|
||||||
if t.len >= 2:
|
if tfNoSideEffect in t.flags:
|
||||||
setLen(result, result.len-1)
|
addSep(prag)
|
||||||
result.add '['
|
add(prag, "noSideEffect")
|
||||||
for i in 0 ..< sonsLen(t):
|
if tfThread in t.flags:
|
||||||
add(result, typeToString(t.sons[i]))
|
addSep(prag)
|
||||||
if i < sonsLen(t) - 1: add(result, ", ")
|
add(prag, "gcsafe")
|
||||||
result.add ']'
|
if t.lockLevel.ord != UnspecifiedLockLevel.ord:
|
||||||
|
addSep(prag)
|
||||||
|
add(prag, "locks: " & $t.lockLevel)
|
||||||
|
if len(prag) != 0: add(result, "{." & prag & ".}")
|
||||||
|
of tyVarargs:
|
||||||
|
result = typeToStr[t.kind] % typeToString(t.sons[0])
|
||||||
|
of tySink:
|
||||||
|
result = "sink " & typeToString(t.sons[0])
|
||||||
|
of tyOwned:
|
||||||
|
result = "owned " & typeToString(t.sons[0])
|
||||||
else:
|
else:
|
||||||
result.add typeToString(t.sons[0])
|
result = typeToStr[t.kind]
|
||||||
of tyRange:
|
result.addTypeFlags(t)
|
||||||
result = "range "
|
result = typeToString(typ, prefer)
|
||||||
if t.n != nil and t.n.kind == nkRange:
|
|
||||||
result.add rangeToStr(t.n)
|
|
||||||
if prefer != preferExported:
|
|
||||||
result.add("(" & typeToString(t.sons[0]) & ")")
|
|
||||||
of tyProc:
|
|
||||||
result = if tfIterator in t.flags: "iterator "
|
|
||||||
elif t.owner != nil:
|
|
||||||
case t.owner.kind
|
|
||||||
of skTemplate: "template "
|
|
||||||
of skMacro: "macro "
|
|
||||||
of skConverter: "converter "
|
|
||||||
else: "proc "
|
|
||||||
else:
|
|
||||||
"proc "
|
|
||||||
if tfUnresolved in t.flags: result.add "[*missing parameters*]"
|
|
||||||
result.add "("
|
|
||||||
for i in 1 ..< sonsLen(t):
|
|
||||||
if t.n != nil and i < t.n.len and t.n[i].kind == nkSym:
|
|
||||||
add(result, t.n[i].sym.name.s)
|
|
||||||
add(result, ": ")
|
|
||||||
add(result, typeToString(t.sons[i]))
|
|
||||||
if i < sonsLen(t) - 1: add(result, ", ")
|
|
||||||
add(result, ')')
|
|
||||||
if t.len > 0 and t.sons[0] != nil: add(result, ": " & typeToString(t.sons[0]))
|
|
||||||
var prag = if t.callConv == ccDefault: "" else: CallingConvToStr[t.callConv]
|
|
||||||
if tfNoSideEffect in t.flags:
|
|
||||||
addSep(prag)
|
|
||||||
add(prag, "noSideEffect")
|
|
||||||
if tfThread in t.flags:
|
|
||||||
addSep(prag)
|
|
||||||
add(prag, "gcsafe")
|
|
||||||
if t.lockLevel.ord != UnspecifiedLockLevel.ord:
|
|
||||||
addSep(prag)
|
|
||||||
add(prag, "locks: " & $t.lockLevel)
|
|
||||||
if len(prag) != 0: add(result, "{." & prag & ".}")
|
|
||||||
of tyVarargs:
|
|
||||||
result = typeToStr[t.kind] % typeToString(t.sons[0])
|
|
||||||
of tySink:
|
|
||||||
result = "sink " & typeToString(t.sons[0])
|
|
||||||
of tyOwned:
|
|
||||||
result = "owned " & typeToString(t.sons[0])
|
|
||||||
else:
|
|
||||||
result = typeToStr[t.kind]
|
|
||||||
result.addTypeFlags(t)
|
|
||||||
|
|
||||||
proc firstOrd*(conf: ConfigRef; t: PType): Int128 =
|
proc firstOrd*(conf: ConfigRef; t: PType): Int128 =
|
||||||
case t.kind
|
case t.kind
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ tsigmatch.nim(143, 13) Error: type mismatch: got <array[0..0, proc (x: int){.gcs
|
||||||
but expected one of:
|
but expected one of:
|
||||||
proc takesFuncs(fs: openArray[proc (x: int) {.gcsafe, locks: 0.}])
|
proc takesFuncs(fs: openArray[proc (x: int) {.gcsafe, locks: 0.}])
|
||||||
first type mismatch at position: 1
|
first type mismatch at position: 1
|
||||||
required type for fs: openarray[proc (x: int){.closure, gcsafe, locks: 0.}]
|
required type for fs: openArray[proc (x: int){.closure, gcsafe, locks: 0.}]
|
||||||
but expression '[proc (x: int) {.gcsafe, locks: 0.} = echo [x]]' is of type: array[0..0, proc (x: int){.gcsafe, locks: 0.}]
|
but expression '[proc (x: int) {.gcsafe, locks: 0.} = echo [x]]' is of type: array[0..0, proc (x: int){.gcsafe, locks: 0.}]
|
||||||
|
|
||||||
expression: takesFuncs([proc (x: int) {.gcsafe, locks: 0.} = echo [x]])
|
expression: takesFuncs([proc (x: int) {.gcsafe, locks: 0.} = echo [x]])
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ twrong_at_operator.nim(22, 30) Error: type mismatch: got <array[0..0, type int]>
|
||||||
but expected one of:
|
but expected one of:
|
||||||
proc `@`[T](a: openArray[T]): seq[T]
|
proc `@`[T](a: openArray[T]): seq[T]
|
||||||
first type mismatch at position: 1
|
first type mismatch at position: 1
|
||||||
required type for a: openarray[T]
|
required type for a: openArray[T]
|
||||||
but expression '[int]' is of type: array[0..0, type int]
|
but expression '[int]' is of type: array[0..0, type int]
|
||||||
proc `@`[IDX, T](a: sink array[IDX, T]): seq[T]
|
proc `@`[IDX, T](a: sink array[IDX, T]): seq[T]
|
||||||
first type mismatch at position: 1
|
first type mismatch at position: 1
|
||||||
|
|
|
||||||
|
|
@ -14,3 +14,32 @@ block: # isNamedTuple
|
||||||
doAssert not Foo3.isNamedTuple
|
doAssert not Foo3.isNamedTuple
|
||||||
doAssert not Foo4.isNamedTuple
|
doAssert not Foo4.isNamedTuple
|
||||||
doAssert not (1,).type.isNamedTuple
|
doAssert not (1,).type.isNamedTuple
|
||||||
|
|
||||||
|
proc typeToString*(t: typedesc, prefer = "preferTypeName"): string {.magic: "TypeTrait".}
|
||||||
|
## Returns the name of the given type, with more flexibility than `name`,
|
||||||
|
## and avoiding the potential clash with a variable named `name`.
|
||||||
|
## prefer = "preferResolved" will resolve type aliases recursively.
|
||||||
|
# Move to typetraits.nim once api stabilized.
|
||||||
|
|
||||||
|
block: # typeToString
|
||||||
|
type MyInt = int
|
||||||
|
type
|
||||||
|
C[T0, T1] = object
|
||||||
|
type C2=C # alias => will resolve as C
|
||||||
|
type C2b=C # alias => will resolve as C (recursively)
|
||||||
|
type C3[U,V] = C[V,U]
|
||||||
|
type C4[X] = C[X,X]
|
||||||
|
template name2(T): string = typeToString(T, "preferResolved")
|
||||||
|
doAssert MyInt.name2 == "int"
|
||||||
|
doAssert C3[MyInt, C2b].name2 == "C3[int, C]"
|
||||||
|
# C3 doesn't get resolved to C, not an alias (nor does C4)
|
||||||
|
doAssert C2b[MyInt, C4[cstring]].name2 == "C[int, C4[cstring]]"
|
||||||
|
doAssert C4[MyInt].name2 == "C4[int]"
|
||||||
|
when BiggestFloat is float and cint is int:
|
||||||
|
doAssert C2b[cint, BiggestFloat].name2 == "C3[int, C3[float, int32]]"
|
||||||
|
|
||||||
|
template name3(T): string = typeToString(T, "preferMixed")
|
||||||
|
doAssert MyInt.name3 == "MyInt{int}"
|
||||||
|
doAssert (tuple[a: MyInt, b: float]).name3 == "tuple[a: MyInt{int}, b: float]"
|
||||||
|
doAssert (tuple[a: C2b[MyInt, C4[cstring]], b: cint, c: float]).name3 ==
|
||||||
|
"tuple[a: C2b{C}[MyInt{int}, C4[cstring]], b: cint{int32}, c: float]"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
errormsg: "invalid type: 'openarray[int]' for result"
|
errormsg: "invalid type: 'openArray[int]' for result"
|
||||||
line: 6
|
line: 6
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue