Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

internal: use custom rendering for --expandArc #813

Merged
merged 2 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion compiler/ast/report_enums.nim
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,6 @@ type

rsemEffectsListingHint
rsemExpandMacro = "ExpandMacro" ## Trace macro expansion progress
rsemExpandArc = "ExpandArc"

rsemCompilesReport
rsemNonMatchingCandidates
Expand Down
2 changes: 1 addition & 1 deletion compiler/ast/reports_sem.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## module with semantic analysis legacy reports definitions

import
compiler/ast/[

Check warning on line 4 in compiler/ast/reports_sem.nim

View workflow job for this annotation

GitHub Actions / Build release binaries (macOS)

imported and not used: 'reports_base' [UnusedImport]

Check warning on line 4 in compiler/ast/reports_sem.nim

View workflow job for this annotation

GitHub Actions / Build release binaries (Linux)

imported and not used: 'reports_base' [UnusedImport]

Check warning on line 4 in compiler/ast/reports_sem.nim

View workflow job for this annotation

GitHub Actions / Build docs and release artifacts (Linux)

imported and not used: 'reports_base' [UnusedImport]

Check warning on line 4 in compiler/ast/reports_sem.nim

View workflow job for this annotation

GitHub Actions / Build docs and release artifacts (macOS)

imported and not used: 'reports_base' [UnusedImport]
report_enums,
ast_types,
lineinfos,
Expand Down Expand Up @@ -151,7 +151,7 @@
of rsemReportTwoSym + rsemReportOneSym + rsemReportListSym:
symbols*: seq[PSym]

of rsemExpandMacro, rsemPattern, rsemExpandArc:
of rsemExpandMacro, rsemPattern:
expandedAst*: PNode

of rsemLockLevelMismatch, rsemMethodLockMismatch:
Expand Down
273 changes: 273 additions & 0 deletions compiler/backend/cgirutils.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
## Non-essential code-generator IR related routines.

import
std/[
strutils
],
compiler/ast/[
ast_types,
ast_query,
typesrenderer
],
compiler/utils/[
idioms
]

from compiler/ast/renderer import renderTree, TRenderFlag

type
RenderCtx = object
syms: seq[PSym]
## remembers the already-rendered symbols. Used to provide unique names.

proc disambiguate(c: var RenderCtx, s: PSym): int =
## Computes and returns a number to append to the symbol name in order to
## make it unique in the output. This way, multiple different symbols sharing
## the same name can be disambiguated.
result = 0
for it in c.syms.items:
if it == s:
return
elif it.name.id == s.name.id: # same name?
inc result

c.syms.add s # remember the symbol

proc render(c: var RenderCtx, ind: int, n: PNode, res: var string) =
template add(s: var string, n: PNode) =
render(c, ind, n, res)

template indent(extra = 1) =
if res.len > 0 and res[^1] == ' ':
# remove trailing space
res.setLen(res.len - 1)
res.add "\n"
res.add repeat(" ", ind + extra)

template newLine() =
indent(0)

template renderList(n: PNode, sep: untyped; start: int = 0; fin: int = 0) =
## Renders the items in the slice ``start..<n.len - fin``
for i in start..<n.len-fin:
if i > start:
sep
res.add n[i]

template renderList(n: PNode, sep: string; start: int = 0; fin: int = 0) =
## Renders the items in the slice ``start..<n.len - fin``
renderList(n, res.add(sep), start, fin)

case n.kind
of nkIntLit..nkInt64Lit:
res.addInt n.intVal
of nkCharLit, nkUIntLit..nkUInt64Lit:
res.addInt cast[BiggestUInt](n.intVal)
of nkFloatLit..nkFloat128Lit:
res.add $n.floatVal
of nkStrLiterals:
res.add '"'
res.add n.strVal
res.add '"'
of nkNilLit:
res.add "nil"
of nkNimNodeLit:
res.add "<ast>"
of nkSym:
res.add n.sym.name.s
let postfix = disambiguate(c, n.sym)
if postfix > 0 and n.sym.magic == mNone:
res.add "_" & $postfix

# the rendered code is currently used for the ``--expandArc``, so we also
# highlight cursor locals
if sfCursor in n.sym.flags:
res.add "_cursor"
of nkType:
if n.typ.sym != nil:
res.add $n.typ
else:
res.add "[type node]"
of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref, nkHiddenStdConv, nkChckRange, nkChckRange64, nkChckRangeF:
res.add n[0]
of nkAddr:
res.add "addr "
res.add n[0]
of nkDerefExpr:
res.add n[0]
res.add "[]"
of nkDotExpr:
res.add n[0]
res.add '.'
res.add n[1]
of nkBracketExpr:
res.add n[0]
res.add '['
res.add n[1]
res.add ']'
of nkRange:
res.add n[0]
res.add ".."
res.add n[1]
of nkCast:
res.add "cast["
res.add $n[0].typ
res.add "]("
res.add n[1]
res.add ")"
of nkStringToCString:
res.add "cstring("
res.add n[0]
res.add ')'
of nkCStringToString:
res.add "string("
res.add n[0]
res.add ')'
of nkConv:
res.add n[0]
res.add '('
res.add n[1]
res.add ')'
of nkObjUpConv, nkObjDownConv:
res.add $n.typ
res.add "("
res.add n[0]
res.add ")"
of nkExprColonExpr:
res.add n[0]
res.add ": "
res.add n[1]
of nkCall:
res.add n[0]
res.add '('
let ind = ind + 1
renderList(n, ", ", 1)
res.add ')'

of nkObjConstr:
res.add $n[0].typ
res.add '('
renderList(n, ", ", 1)
res.add ')'
of nkTupleConstr, nkClosure:
res.add '('
renderList(n, ", ")
res.add ')'
of nkBracket:
res.add '['
renderList(n, ", ")
res.add ']'
of nkCurly:
res.add '{'
renderList(n, ", ")
res.add '}'

of nkAsgn, nkFastAsgn:
res.add n[0]
res.add " = "
let ind = ind + 1
res.add n[1]
of nkVarSection, nkLetSection:
for i, def in n.pairs:
if i > 0:
newLine()
res.add "var "
res.add def[0]
if def[2].kind != nkEmpty:
res.add " = "
let ind = ind + 1
res.add def[2]
of nkPragma:
# re-use the ``PNode`` rendering
res.add renderTree(n, {renderIr, renderNoComments})
of nkReturnStmt:
res.add "return"
of nkDiscardStmt:
res.add "discard "
res.add n[0]
of nkBreakStmt:
if n[0].kind == nkEmpty:
res.add "break"
else:
res.add "break "
res.add n[0]
of nkRaiseStmt:
if n[0].kind == nkEmpty:
res.add "raise"
else:
res.add "raise "
res.add n[0]
of nkAsmStmt:
res.add "asm "
let ind = ind + 1
renderList(n, ", ")
res.add ""
of nkWhileStmt:
res.add "while true:"
indent()
render(c, ind + 1, n[1], res)
of nkBlockStmt:
if n[0].kind == nkEmpty:
res.add "block:"
else:
res.add "block "
res.add n[0]
res.add ":"
indent()
render(c, ind + 1, n[1], res)
of nkIfStmt:
res.add "if "
res.add n[0][0]
res.add ':'
indent()
render(c, ind + 1, n[0][1], res)
of nkCaseStmt:
res.add "case "
res.add n[0]
for i in 1..<n.len:
newLine()
case n.kind
of nkOfBranch:
res.add "of "
renderList(n[i], ", ", 1, 1)
of nkElse:
res.add "else"
else:
unreachable()

res.add ":"
indent()
render(c, ind + 1, n[i][^1], res)
of nkTryStmt:
res.add "try:"
indent()
render(c, ind + 1, n[0], res)
for i in 1..<n.len:
case n[i].kind
of nkExceptBranch:
newLine()
res.add "except:"
indent()
render(c, ind + 1, n[i][^1], res)
of nkFinally:
newLine()
res.add "finally:"
indent()
render(c, ind + 1, n[i][0], res)
else:
unreachable()
of nkStmtListExpr:
newLine()
renderList(n, newLine())
of nkStmtList:
renderList(n, newLine())
of nkWithSons + nkWithoutSons - codegenExprNodeKinds -
{nkExprColonExpr, nkRange} + {nkEmpty}:
unreachable(n.kind)

proc render*(n: PNode): string =
## Renders `n` to human-readable code that tries to emulate the shape of the
## high-level language. The output is meant for debugging and tracing and is
## not guaranteed to have a stable format.
var c = RenderCtx()
render(c, 0, n, result)
12 changes: 0 additions & 12 deletions compiler/front/cli_reporter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -520,17 +520,6 @@ proc reportBody*(conf: ConfigRef, r: SemReport): string =
r.typ.kind == tyProc:
result.add(" = ", typeToString(r.typ, preferDesc))


of rsemExpandArc:
result.add(
"--expandArc: ",
r.symstr,
"\n",
r.expandedAst.renderTree({renderIr, renderNoComments}),
"\n",
"-- end of expandArc ------------------------"
)

of rsemCannotBorrow:
result.add(
"cannot borrow ",
Expand Down Expand Up @@ -2238,7 +2227,6 @@ proc reportBody*(conf: ConfigRef, r: SemReport): string =


const standalone = {
rsemExpandArc, # Original compiler did not consider it as a hint
rvmStackTrace, # Always associated with extra report
rsemDiagnostics, # Wraps other reports
}
Expand Down
7 changes: 1 addition & 6 deletions compiler/front/options.nim
Original file line number Diff line number Diff line change
Expand Up @@ -708,9 +708,6 @@ type
writeForceEnabled

func writabilityKind*(conf: ConfigRef, r: Report): ReportWritabilityKind =
const forceWrite =
{rsemExpandArc} # Not a hint, just legacy reports overeach

let compTimeCtx = conf.m.errorOutputs == {}
## indicates whether we're in a `compiles` or `constant expression
## evaluation` context. `sem` and `semexprs` in particular will clear
Expand Down Expand Up @@ -743,9 +740,7 @@ func writabilityKind*(conf: ConfigRef, r: Report): ReportWritabilityKind =

elif (
# Not explicitly enabled
not conf.isEnabled(r) and
# And not added for forced write
r.kind notin forceWrite
not conf.isEnabled(r)
) or (
# Or we are in the special hack mode for `compiles()` processing
compTimeCtx
Expand Down
19 changes: 11 additions & 8 deletions compiler/sem/injectdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ import
from compiler/ast/reports_sem import SemReport
from compiler/ast/report_enums import ReportKind

# XXX: we shouldn't need to be concerned with rendering backend-
# IR to text here
from compiler/backend/cgirutils import render

type
AnalyseCtx = object
cfg: ControlFlowGraph
Expand Down Expand Up @@ -1317,12 +1321,11 @@ proc injectDestructorCalls*(g: ModuleGraph; idgen: IdGenerator; owner: PSym;
apply(changes)

if g.config.arcToExpand.hasKey(owner.name.s):
# the diagnostic expects a ``PNode`` AST, so we first have to tranlsate
# the MIR code into one. While this is inefficient, ``expandArc`` is only
# meant as a utility, so it's okay for now.
# due to some parts of it being very declarative, rendering and echoing
# the MIR code wouldn't be very useful, so we turn it into backend IR
# first, which we then render to text
# XXX: this needs a deeper rethink
let n = generateAST(g, idgen, owner, tree, sourceMap)
g.config.localReport(SemReport(
kind: rsemExpandArc,
sym: owner,
expandedAst: n
))
g.config.msgWrite("--expandArc: " & owner.name.s & "\n")
g.config.msgWrite(render(n))
g.config.msgWrite("\n-- end of expandArc ------------------------\n")
Loading
Loading