diff --git a/compiler/ast/report_enums.nim b/compiler/ast/report_enums.nim index ade16f72491..de5834f85ea 100644 --- a/compiler/ast/report_enums.nim +++ b/compiler/ast/report_enums.nim @@ -818,7 +818,6 @@ type rsemEffectsListingHint rsemExpandMacro = "ExpandMacro" ## Trace macro expansion progress - rsemExpandArc = "ExpandArc" rsemCompilesReport rsemNonMatchingCandidates diff --git a/compiler/ast/reports_sem.nim b/compiler/ast/reports_sem.nim index 15213cf4736..fe5df11738c 100644 --- a/compiler/ast/reports_sem.nim +++ b/compiler/ast/reports_sem.nim @@ -151,7 +151,7 @@ type of rsemReportTwoSym + rsemReportOneSym + rsemReportListSym: symbols*: seq[PSym] - of rsemExpandMacro, rsemPattern, rsemExpandArc: + of rsemExpandMacro, rsemPattern: expandedAst*: PNode of rsemLockLevelMismatch, rsemMethodLockMismatch: diff --git a/compiler/backend/cgirutils.nim b/compiler/backend/cgirutils.nim new file mode 100644 index 00000000000..66d3760274a --- /dev/null +++ b/compiler/backend/cgirutils.nim @@ -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.. 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.." + 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..