Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
179: `cli_reporter` / `typesrenderer` refactor  r=haxscramper a=tandy-1000

Small refactor moving all leftover string formatting for P(Node|Sym|Type) from types.nim to typesrenderer.nim.
Removed some dead code, cleaned up some imports, reshuffled some consts & procs.
String formatting / rendering procs should not be in types.nim, and this should be fixed by this PR.

fixes nim-works#167

Co-authored-by: tandy <[email protected]>
  • Loading branch information
bors[bot] and tandy-1000 authored Jan 27, 2022
2 parents b9ea9a1 + a2d17a3 commit 006bdd3
Show file tree
Hide file tree
Showing 13 changed files with 403 additions and 328 deletions.
1 change: 0 additions & 1 deletion compiler/ast/reports.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1136,7 +1136,6 @@ type
SemTypeMismatch* = object
formalTypeKind*: set[TTypeKind]
actualType*, formalType*: PType
descriptionStr*: string

SemCallMismatch* = object
## Description of the single candidate mismatch. This type is later
Expand Down
320 changes: 0 additions & 320 deletions compiler/ast/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import
trees,
renderer,
lineinfos,
astmsgs,
errorhandling,
reports
],
Expand Down Expand Up @@ -51,17 +50,6 @@ type
# most useful, shows: symbol + resolved symbols if it differs, e.g.:
# tuple[a: MyInt{int}, b: float]

proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string

proc addTypeDeclVerboseMaybe*(result: var string, conf: ConfigRef; typ: PType) =
if optDeclaredLocs in conf.globalOptions:
result.add typeToString(typ, preferMixed)
result.addDeclaredLoc(conf, typ)
else:
result.add typeToString(typ)

template `$`*(typ: PType): string = typeToString(typ)

proc base*(t: PType): PType =
result = t[0]

Expand Down Expand Up @@ -153,32 +141,6 @@ proc isIntLit*(t: PType): bool {.inline.} =
proc isFloatLit*(t: PType): bool {.inline.} =
result = t.kind == tyFloat and t.n != nil and t.n.kind == nkFloatLit

proc addTypeHeader*(result: var string, conf: ConfigRef; typ: PType; prefer: TPreferedDesc = preferMixed; getDeclarationPath = true) =
result.add typeToString(typ, prefer)
if getDeclarationPath: result.addDeclaredLoc(conf, typ.sym)

proc getProcHeader*(
conf: ConfigRef; sym: PSym; prefer: TPreferedDesc = preferName; getDeclarationPath = true): string =
assert sym != nil
# consider using `skipGenericOwner` to avoid fun2.fun2 when fun2 is generic
result = sym.owner.name.s & '.' & sym.name.s
if sym.kind in routineKinds:
result.add '('
var n = sym.typ.n
for i in 1..<n.len:
let p = n[i]
if p.kind == nkSym:
result.add(p.sym.name.s)
result.add(": ")
result.add(typeToString(p.sym.typ, prefer))
if i != n.len-1: result.add(", ")
else:
result.add renderTree(p)
result.add(')')
if n[0].typ != nil:
result.add(": " & typeToString(n[0].typ, prefer))
if getDeclarationPath: result.addDeclaredLoc(conf, sym)

proc elemType*(t: PType): PType =
assert(t != nil)
case t.kind
Expand Down Expand Up @@ -449,38 +411,6 @@ proc mutateType(t: PType, iter: TTypeMutator, closure: RootRef): PType =
var marker = initIntSet()
result = mutateTypeAux(marker, t, iter, closure)

proc valueToString(a: PNode): string =
case a.kind
of nkCharLit..nkUInt64Lit: result = $a.intVal
of nkFloatLit..nkFloat128Lit: result = $a.floatVal
of nkStrLit..nkTripleStrLit: result = a.strVal
else: result = "<invalid value>"

proc rangeToStr(n: PNode): string =
assert(n.kind == nkRange)
result = valueToString(n[0]) & ".." & valueToString(n[1])

const
typeToStr: array[TTypeKind, string] = ["None", "bool", "char", "empty",
"Alias", "typeof(nil)", "untyped", "typed", "typeDesc",
# xxx typeDesc=>typedesc: typedesc is declared as such, and is 10x more common.
"GenericInvocation", "GenericBody", "GenericInst", "GenericParam",
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
"set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
"pointer", "OpenArray[$1]", "string", "cstring", "Forward",
"int", "int8", "int16", "int32", "int64",
"float", "float32", "float64", "float128",
"uint", "uint8", "uint16", "uint32", "uint64",
"owned", "sink",
"lent ", "varargs[$1]", "UncheckedArray[$1]", "Error Type",
"BuiltInTypeClass", "UserTypeClass",
"UserTypeClassInst", "CompositeTypeClass", "inferred",
"and", "or", "not", "any", "static", "TypeFromExpr", "concept", # xxx bugfix
"void", "iterable"]

const preferToResolveSymbols = {preferName, preferTypeName, preferModuleInfo,
preferGenericArg, preferResolved, preferMixed}

template bindConcreteTypeToUserTypeClass*(tc, concrete: PType) =
tc.add concrete
tc.flags.incl tfResolved
Expand All @@ -494,255 +424,6 @@ template bindConcreteTypeToUserTypeClass*(tc, concrete: PType) =
template isResolvedUserTypeClass*(t: PType): bool =
tfResolved in t.flags

proc addTypeFlags(name: var string, typ: PType) {.inline.} =
if tfNotNil in typ.flags: name.add(" not nil")

proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
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 =
result = ""
let prefer = getPrefer(prefer)
let t = typ
if t == nil: return
if prefer in preferToResolveSymbols and t.sym != nil and
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[0].kind != tyAlias:
result = typeToString(t[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.len > 0:
result.add ": "
var first = true
for son in t.sons:
if not first: result.add " or "
result.add son.typeToString
first = false
else:
result = t.sym.owner.name.s & '.' & t.sym.name.s
result.addTypeFlags(t)
return
case t.kind
of tyInt:
if not isIntLit(t) or prefer == preferExported:
result = typeToStr[t.kind]
else:
if prefer == preferGenericArg:
result = $t.n.intVal
else:
result = "int literal(" & $t.n.intVal & ")"
of tyGenericInst, tyGenericInvocation:
result = typeToString(t[0]) & '['
for i in 1..<t.len-ord(t.kind != tyGenericInvocation):
if i > 1: result.add(", ")
result.add(typeToString(t[i], preferGenericArg))
result.add(']')
of tyGenericBody:
result = typeToString(t.lastSon) & '['
for i in 0..<t.len-1:
if i > 0: result.add(", ")
result.add(typeToString(t[i], preferTypeName))
result.add(']')
of tyTypeDesc:
if t[0].kind == tyNone: result = "typedesc"
else: result = "typedesc[" & typeToString(t[0]) & "]"
of tyStatic:
if prefer == preferGenericArg and t.n != nil:
result = t.n.renderTree
else:
result = "static[" & (if t.len > 0: typeToString(t[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..<t.len - 1:
if i > 1: result.add(", ")
result.add(typeToString(t[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[0])
of tyUntyped:
#internalAssert t.len == 0
result = "untyped"
of tyFromExpr:
if t.n == nil:
result = "unknown"
else:
result = "typeof(" & renderTree(t.n) & ")"
of tyArray:
result = "array"
if t.len > 0:
if t[0].kind == tyRange:
result &= "[" & rangeToStr(t[0].n) & ", " &
typeToString(t[1]) & ']'
else:
result &= "[" & typeToString(t[0]) & ", " &
typeToString(t[1]) & ']'
of tyUncheckedArray:
result = "UncheckedArray"
if t.len > 0:
result &= "[" & typeToString(t[0]) & ']'
of tySequence:
if t.sym != nil and prefer != preferResolved:
result = t.sym.name.s
else:
result = "seq"
if t.len > 0:
result &= "[" & typeToString(t[0]) & ']'
of tyOrdinal:
result = "ordinal"
if t.len > 0:
result &= "[" & typeToString(t[0]) & ']'
of tySet:
result = "set"
if t.len > 0:
result &= "[" & typeToString(t[0]) & ']'
of tyOpenArray:
result = "openArray"
if t.len > 0:
result &= "[" & typeToString(t[0]) & ']'
of tyDistinct:
result = "distinct " & typeToString(t[0],
if prefer == preferModuleInfo: preferModuleInfo else: preferTypeName)
of tyIterable:
# xxx factor this pattern
result = "iterable"
if t.len > 0:
result &= "[" & typeToString(t[0]) & ']'
of tyTuple:
# we iterate over t.sons here, because t.n may be nil
if t.n != nil:
result = "tuple["
assert(t.n.len == t.len)
for i in 0..<t.n.len:
assert(t.n[i].kind == nkSym)
result.add(t.n[i].sym.name.s & ": " & typeToString(t[i]))
if i < t.n.len - 1: result.add(", ")
result.add(']')
elif t.len == 0:
result = "tuple[]"
else:
result = "("
for i in 0..<t.len:
result.add(typeToString(t[i]))
if i < t.len - 1: result.add(", ")
elif t.len == 1: result.add(",")
result.add(')')
of tyPtr, tyRef, tyVar, tyLent:
result = typeToStr[t.kind]
if t.len >= 2:
setLen(result, result.len-1)
result.add '['
for i in 0..<t.len:
result.add(typeToString(t[i]))
if i < t.len - 1: result.add(", ")
result.add ']'
else:
result.add typeToString(t[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[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..<t.len:
if t.n != nil and i < t.n.len and t.n[i].kind == nkSym:
result.add(t.n[i].sym.name.s)
result.add(": ")
result.add(typeToString(t[i]))
if i < t.len - 1: result.add(", ")
result.add(')')
if t.len > 0 and t[0] != nil: result.add(": " & typeToString(t[0]))
var prag = if t.callConv == ccNimCall and tfExplicitCallConv notin t.flags: "" else: $t.callConv
if tfNoSideEffect in t.flags:
addSep(prag)
prag.add("noSideEffect")
if tfThread in t.flags:
addSep(prag)
prag.add("gcsafe")
if t.lockLevel.ord != UnspecifiedLockLevel.ord:
addSep(prag)
prag.add("locks: " & $t.lockLevel)
if prag.len != 0: result.add("{." & prag & ".}")
of tyVarargs:
result = typeToStr[t.kind] % typeToString(t[0])
of tySink:
result = "sink " & typeToString(t[0])
of tyOwned:
result = "owned " & typeToString(t[0])
else:
result = typeToStr[t.kind]
result.addTypeFlags(t)
result = typeToString(typ, prefer)

proc firstOrd*(conf: ConfigRef; t: PType): Int128 =
case t.kind
of tyBool, tyChar, tySequence, tyOpenArray, tyString, tyVarargs, tyProxy:
Expand Down Expand Up @@ -1583,7 +1264,6 @@ proc typeMismatch*(
result = SemTypeMismatch(
actualType: actual,
formalType: formal,
descriptionStr: typeToString(formal, preferDesc)
)

proc typeMismatch*(
Expand Down
Loading

0 comments on commit 006bdd3

Please sign in to comment.