* 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,7 +458,16 @@ 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
|
||||||
|
proc getPrefer(prefer: TPreferedDesc): TPreferedDesc =
|
||||||
|
if preferToplevel in {preferResolved, preferMixed}:
|
||||||
|
preferToplevel # sticky option
|
||||||
|
else:
|
||||||
|
prefer
|
||||||
|
|
||||||
|
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
|
let prefer = getPrefer(prefer)
|
||||||
|
let t = typ
|
||||||
result = ""
|
result = ""
|
||||||
if t == nil: return
|
if t == nil: return
|
||||||
if prefer in preferToResolveSymbols and t.sym != nil and
|
if prefer in preferToResolveSymbols and t.sym != nil and
|
||||||
|
|
@ -459,7 +476,21 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
|
result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
|
||||||
elif t.kind == tyAlias and t.sons[0].kind != tyAlias:
|
elif t.kind == tyAlias and t.sons[0].kind != tyAlias:
|
||||||
result = typeToString(t.sons[0])
|
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:
|
elif prefer in {preferName, preferTypeName} or t.sym.owner.isNil:
|
||||||
|
# note: should probably be: {preferName, preferTypeName, preferGenericArg}
|
||||||
result = t.sym.name.s
|
result = t.sym.name.s
|
||||||
if t.kind == tyGenericParam and t.sonsLen > 0:
|
if t.kind == tyGenericParam and t.sonsLen > 0:
|
||||||
result.add ": "
|
result.add ": "
|
||||||
|
|
@ -521,7 +552,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
of tyProc: "proc"
|
of tyProc: "proc"
|
||||||
of tyObject: "object"
|
of tyObject: "object"
|
||||||
of tyTuple: "tuple"
|
of tyTuple: "tuple"
|
||||||
of tyOpenArray: "openarray"
|
of tyOpenArray: "openArray"
|
||||||
else: typeToStr[t.base.kind]
|
else: typeToStr[t.base.kind]
|
||||||
of tyInferred:
|
of tyInferred:
|
||||||
let concrete = t.previouslyInferred
|
let concrete = t.previouslyInferred
|
||||||
|
|
@ -572,7 +603,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
of tySet:
|
of tySet:
|
||||||
result = "set[" & typeToString(t.sons[0]) & ']'
|
result = "set[" & typeToString(t.sons[0]) & ']'
|
||||||
of tyOpenArray:
|
of tyOpenArray:
|
||||||
result = "openarray[" & typeToString(t.sons[0]) & ']'
|
result = "openArray[" & typeToString(t.sons[0]) & ']'
|
||||||
of tyDistinct:
|
of tyDistinct:
|
||||||
result = "distinct " & typeToString(t.sons[0],
|
result = "distinct " & typeToString(t.sons[0],
|
||||||
if prefer == preferModuleInfo: preferModuleInfo else: preferTypeName)
|
if prefer == preferModuleInfo: preferModuleInfo else: preferTypeName)
|
||||||
|
|
@ -652,6 +683,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
else:
|
else:
|
||||||
result = typeToStr[t.kind]
|
result = typeToStr[t.kind]
|
||||||
result.addTypeFlags(t)
|
result.addTypeFlags(t)
|
||||||
|
result = typeToString(typ, prefer)
|
||||||
|
|
||||||
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