diff options
Diffstat (limited to 'rod/rnimsyn.nim')
-rw-r--r-- | rod/rnimsyn.nim | 1074 |
1 files changed, 0 insertions, 1074 deletions
diff --git a/rod/rnimsyn.nim b/rod/rnimsyn.nim deleted file mode 100644 index 60cfd38b1..000000000 --- a/rod/rnimsyn.nim +++ /dev/null @@ -1,1074 +0,0 @@ -# -# -# The Nimrod Compiler -# (c) Copyright 2010 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -# This module implements the renderer of the standard Nimrod representation. - -import - scanner, options, idents, strutils, ast, msgs, lists - -type - TRenderFlag* = enum - renderNone, renderNoBody, renderNoComments, renderDocComments, - renderNoPragmas, renderIds - TRenderFlags* = set[TRenderFlag] - TRenderTok*{.final.} = object - kind*: TTokType - length*: int16 - - TRenderTokSeq* = seq[TRenderTok] - TSrcGen*{.final.} = object - indent*: int - lineLen*: int - pos*: int # current position for iteration over the buffer - idx*: int # current token index for iteration over the buffer - tokens*: TRenderTokSeq - buf*: string - pendingNL*: int # negative if not active; else contains the - # indentation value - comStack*: seq[PNode] # comment stack - flags*: TRenderFlags - - -proc renderModule*(n: PNode, filename: string, renderFlags: TRenderFlags = {}) -proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string -proc initTokRender*(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) -proc getNextTok*(r: var TSrcGen, kind: var TTokType, literal: var string) -# implementation -# We render the source code in a two phases: The first -# determines how long the subtree will likely be, the second -# phase appends to a buffer that will be the output. - -const - IndentWidth = 2 - longIndentWid = 4 - MaxLineLen = 80 - LineCommentColumn = 30 - -proc InitSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) = - g.comStack = @[] - g.tokens = @[] - g.indent = 0 - g.lineLen = 0 - g.pos = 0 - g.idx = 0 - g.buf = "" - g.flags = renderFlags - g.pendingNL = - 1 - -proc addTok(g: var TSrcGen, kind: TTokType, s: string) = - var length = len(g.tokens) - setlen(g.tokens, length + 1) - g.tokens[length].kind = kind - g.tokens[length].length = int16(len(s)) - add(g.buf, s) - -proc addPendingNL(g: var TSrcGen) = - if g.pendingNL >= 0: - addTok(g, tkInd, "\n" & repeatChar(g.pendingNL)) - g.lineLen = g.pendingNL - g.pendingNL = - 1 - -proc putNL(g: var TSrcGen, indent: int) = - if g.pendingNL >= 0: addPendingNL(g) - else: addTok(g, tkInd, "\n") - g.pendingNL = indent - g.lineLen = indent - -proc putNL(g: var TSrcGen) = - putNL(g, g.indent) - -proc optNL(g: var TSrcGen, indent: int) = - g.pendingNL = indent - g.lineLen = indent # BUGFIX - -proc optNL(g: var TSrcGen) = - optNL(g, g.indent) - -proc indentNL(g: var TSrcGen) = - inc(g.indent, indentWidth) - g.pendingNL = g.indent - g.lineLen = g.indent - -proc Dedent(g: var TSrcGen) = - dec(g.indent, indentWidth) - assert(g.indent >= 0) - if g.pendingNL > indentWidth: - Dec(g.pendingNL, indentWidth) - Dec(g.lineLen, indentWidth) - -proc put(g: var TSrcGen, kind: TTokType, s: string) = - addPendingNL(g) - if len(s) > 0: - addTok(g, kind, s) - inc(g.lineLen, len(s)) - -proc putLong(g: var TSrcGen, kind: TTokType, s: string, lineLen: int) = - # use this for tokens over multiple lines. - addPendingNL(g) - addTok(g, kind, s) - g.lineLen = lineLen - -proc toNimChar(c: Char): string = - case c - of '\0': result = "\\0" - of '\x01'..'\x1F', '\x80'..'\xFF': result = "\\x" & strutils.toHex(ord(c), 2) - of '\'', '\"', '\\': result = '\\' & c - else: result = c & "" - -proc makeNimString(s: string): string = - result = "\"" - for i in countup(0, len(s) + 0 - 1): add(result, toNimChar(s[i])) - add(result, '\"') - -proc putComment(g: var TSrcGen, s: string) = - var i = 0 - var comIndent = 1 - var isCode = (len(s) >= 2) and (s[0 + 1] != ' ') - var ind = g.lineLen - var com = "" - while true: - case s[i] - of '\0': - break - of '\x0D': - put(g, tkComment, com) - com = "" - inc(i) - if s[i] == '\x0A': inc(i) - optNL(g, ind) - of '\x0A': - put(g, tkComment, com) - com = "" - inc(i) - optNL(g, ind) - of '#': - add(com, s[i]) - inc(i) - comIndent = 0 - while s[i] == ' ': - add(com, s[i]) - inc(i) - inc(comIndent) - of ' ', '\x09': - add(com, s[i]) - inc(i) - else: - # we may break the comment into a multi-line comment if the line - # gets too long: - # compute length of the following word: - var j = i - while s[j] > ' ': inc(j) - if not isCode and (g.lineLen + (j - i) > MaxLineLen): - put(g, tkComment, com) - com = "" - optNL(g, ind) - com = com & '#' & repeatChar(comIndent) - while s[i] > ' ': - add(com, s[i]) - inc(i) - put(g, tkComment, com) - optNL(g) - -proc maxLineLength(s: string): int = - result = 0 - var i = 0 - var lineLen = 0 - while true: - case s[i] - of '\0': - break - of '\x0D': - inc(i) - if s[i] == '\x0A': inc(i) - result = max(result, lineLen) - lineLen = 0 - of '\x0A': - inc(i) - result = max(result, lineLen) - lineLen = 0 - else: - inc(lineLen) - inc(i) - -proc putRawStr(g: var TSrcGen, kind: TTokType, s: string) = - var i = 0 - var hi = len(s) + 0 - 1 - var str = "" - while i <= hi: - case s[i] - of '\x0D': - put(g, kind, str) - str = "" - inc(i) - if (i <= hi) and (s[i] == '\x0A'): inc(i) - optNL(g, 0) - of '\x0A': - put(g, kind, str) - str = "" - inc(i) - optNL(g, 0) - else: - add(str, s[i]) - inc(i) - put(g, kind, str) - -proc containsNL(s: string): bool = - for i in countup(0, len(s) + 0 - 1): - case s[i] - of '\x0D', '\x0A': - return true - else: - nil - result = false - -proc pushCom(g: var TSrcGen, n: PNode) = - var length = len(g.comStack) - setlen(g.comStack, length + 1) - g.comStack[length] = n - -proc popAllComs(g: var TSrcGen) = - setlen(g.comStack, 0) - -proc popCom(g: var TSrcGen) = - setlen(g.comStack, len(g.comStack) - 1) - -const - Space = " " - -proc shouldRenderComment(g: var TSrcGen, n: PNode): bool = - result = false - if n.comment != nil: - result = not (renderNoComments in g.flags) or - (renderDocComments in g.flags) and startsWith(n.comment, "##") - -proc gcom(g: var TSrcGen, n: PNode) = - assert(n != nil) - if shouldRenderComment(g, n): - if (g.pendingNL < 0) and (len(g.buf) > 0) and (g.buf[len(g.buf)] != ' '): - put(g, tkSpaces, Space) - # Before long comments we cannot make sure that a newline is generated, - # because this might be wrong. But it is no problem in practice. - if (g.pendingNL < 0) and (len(g.buf) > 0) and - (g.lineLen < LineCommentColumn): - var ml = maxLineLength(n.comment) - if ml + LineCommentColumn <= maxLineLen: - put(g, tkSpaces, repeatChar(LineCommentColumn - g.lineLen)) - putComment(g, n.comment) #assert(g.comStack[high(g.comStack)] = n); - -proc gcoms(g: var TSrcGen) = - for i in countup(0, high(g.comStack)): gcom(g, g.comStack[i]) - popAllComs(g) - -proc lsub(n: PNode): int -proc litAux(n: PNode, x: biggestInt, size: int): string = - if nfBase2 in n.flags: result = "0b" & toBin(x, size * 8) - elif nfBase8 in n.flags: result = "0o" & toOct(x, size * 3) - elif nfBase16 in n.flags: result = "0x" & toHex(x, size * 2) - else: result = $(x) - -proc atom(n: PNode): string = - var f: float32 - case n.kind - of nkEmpty: result = "" - of nkIdent: result = n.ident.s - of nkSym: result = n.sym.name.s - of nkStrLit: result = makeNimString(n.strVal) - of nkRStrLit: result = "r\"" & replace(n.strVal, "\"", "\"\"") & '\"' - of nkTripleStrLit: result = "\"\"\"" & n.strVal & "\"\"\"" - of nkCharLit: result = '\'' & toNimChar(chr(int(n.intVal))) & '\'' - of nkIntLit: result = litAux(n, n.intVal, 4) - of nkInt8Lit: result = litAux(n, n.intVal, 1) & "\'i8" - of nkInt16Lit: result = litAux(n, n.intVal, 2) & "\'i16" - of nkInt32Lit: result = litAux(n, n.intVal, 4) & "\'i32" - of nkInt64Lit: result = litAux(n, n.intVal, 8) & "\'i64" - of nkFloatLit: - if n.flags * {nfBase2, nfBase8, nfBase16} == {}: result = $(n.floatVal) - else: result = litAux(n, (cast[PInt64](addr(n.floatVal)))^ , 8) - of nkFloat32Lit: - if n.flags * {nfBase2, nfBase8, nfBase16} == {}: - result = $(n.floatVal) & "\'f32" - else: - f = n.floatVal - result = litAux(n, (cast[PInt32](addr(f)))^ , 4) & "\'f32" - of nkFloat64Lit: - if n.flags * {nfBase2, nfBase8, nfBase16} == {}: - result = $(n.floatVal) & "\'f64" - else: - result = litAux(n, (cast[PInt64](addr(n.floatVal)))^ , 8) & "\'f64" - of nkNilLit: result = "nil" - of nkType: - if (n.typ != nil) and (n.typ.sym != nil): result = n.typ.sym.name.s - else: result = "[type node]" - else: InternalError("rnimsyn.atom " & $n.kind) - -proc lcomma(n: PNode, start: int = 0, theEnd: int = - 1): int = - assert(theEnd < 0) - result = 0 - for i in countup(start, sonsLen(n) + theEnd): - inc(result, lsub(n.sons[i])) - inc(result, 2) # for ``, `` - if result > 0: - dec(result, 2) # last does not get a comma! - -proc lsons(n: PNode, start: int = 0, theEnd: int = - 1): int = - assert(theEnd < 0) - result = 0 - for i in countup(start, sonsLen(n) + theEnd): inc(result, lsub(n.sons[i])) - -proc lsub(n: PNode): int = - # computes the length of a tree - if n == nil: return 0 - if n.comment != nil: return maxLineLen + 1 - case n.kind - of nkTripleStrLit: - if containsNL(n.strVal): result = maxLineLen + 1 - else: result = len(atom(n)) - of nkEmpty..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit: - result = len(atom(n)) - of nkCall, nkBracketExpr, nkConv: result = lsub(n.sons[0]) + lcomma(n, 1) + 2 - of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1]) - of nkCast: result = lsub(n.sons[0]) + lsub(n.sons[1]) + len("cast[]()") - of nkAddr: result = lsub(n.sons[0]) + len("addr()") - of nkHiddenAddr, nkHiddenDeref: result = lsub(n.sons[0]) - of nkCommand: result = lsub(n.sons[0]) + lcomma(n, 1) + 1 - of nkExprEqExpr, nkAsgn, nkFastAsgn: result = lsons(n) + 3 - of nkPar, nkCurly, nkBracket: result = lcomma(n) + 2 - of nkSymChoice: result = lsons(n) + len("()") + sonsLen(n) - 1 - of nkTupleTy: result = lcomma(n) + len("tuple[]") - of nkDotExpr: result = lsons(n) + 1 - of nkBind: result = lsons(n) + len("bind_") - of nkCheckedFieldExpr: result = lsub(n.sons[0]) - of nkLambda: result = lsons(n) + len("lambda__=_") - of nkConstDef, nkIdentDefs: - result = lcomma(n, 0, - 3) - var L = sonsLen(n) - if n.sons[L - 2] != nil: result = result + lsub(n.sons[L - 2]) + 2 - if n.sons[L - 1] != nil: result = result + lsub(n.sons[L - 1]) + 3 - of nkVarTuple: result = lcomma(n, 0, - 3) + len("() = ") + lsub(lastSon(n)) - of nkChckRangeF: result = len("chckRangeF") + 2 + lcomma(n) - of nkChckRange64: result = len("chckRange64") + 2 + lcomma(n) - of nkChckRange: result = len("chckRange") + 2 + lcomma(n) - of nkObjDownConv, nkObjUpConv, nkStringToCString, nkCStringToString, - nkPassAsOpenArray: - result = 2 - if sonsLen(n) >= 1: result = result + lsub(n.sons[0]) - result = result + lcomma(n, 1) - of nkExprColonExpr: result = lsons(n) + 2 - of nkInfix: result = lsons(n) + 2 - of nkPrefix: result = lsons(n) + 1 - of nkPostfix: result = lsons(n) - of nkCallStrLit: result = lsons(n) - of nkPragmaExpr: result = lsub(n.sons[0]) + lcomma(n, 1) - of nkRange: result = lsons(n) + 2 - of nkDerefExpr: result = lsub(n.sons[0]) + 2 - of nkAccQuoted: result = lsub(n.sons[0]) + 2 - of nkIfExpr: - result = lsub(n.sons[0].sons[0]) + lsub(n.sons[0].sons[1]) + lsons(n, 1) + - len("if_:_") - of nkElifExpr: result = lsons(n) + len("_elif_:_") - of nkElseExpr: result = lsub(n.sons[0]) + len("_else:_") # type descriptions - of nkTypeOfExpr: result = lsub(n.sons[0]) + len("type_") - of nkRefTy: result = lsub(n.sons[0]) + len("ref_") - of nkPtrTy: result = lsub(n.sons[0]) + len("ptr_") - of nkVarTy: result = lsub(n.sons[0]) + len("var_") - of nkDistinctTy: result = lsub(n.sons[0]) + len("Distinct_") - of nkTypeDef: result = lsons(n) + 3 - of nkOfInherit: result = lsub(n.sons[0]) + len("of_") - of nkProcTy: result = lsons(n) + len("proc_") - of nkEnumTy: result = lsub(n.sons[0]) + lcomma(n, 1) + len("enum_") - of nkEnumFieldDef: result = lsons(n) + 3 - of nkVarSection: - if sonsLen(n) > 1: result = maxLineLen + 1 - else: result = lsons(n) + len("var_") - of nkReturnStmt: result = lsub(n.sons[0]) + len("return_") - of nkRaiseStmt: result = lsub(n.sons[0]) + len("raise_") - of nkYieldStmt: result = lsub(n.sons[0]) + len("yield_") - of nkDiscardStmt: result = lsub(n.sons[0]) + len("discard_") - of nkBreakStmt: result = lsub(n.sons[0]) + len("break_") - of nkContinueStmt: result = lsub(n.sons[0]) + len("continue_") - of nkPragma: result = lcomma(n) + 4 - of nkCommentStmt: result = len(n.comment) - of nkOfBranch: result = lcomma(n, 0, - 2) + lsub(lastSon(n)) + len("of_:_") - of nkElifBranch: result = lsons(n) + len("elif_:_") - of nkElse: result = lsub(n.sons[0]) + len("else:_") - of nkFinally: result = lsub(n.sons[0]) + len("finally:_") - of nkGenericParams: result = lcomma(n) + 2 - of nkFormalParams: - result = lcomma(n, 1) + 2 - if n.sons[0] != nil: result = result + lsub(n.sons[0]) + 2 - of nkExceptBranch: - result = lcomma(n, 0, -2) + lsub(lastSon(n)) + len("except_:_") - else: result = maxLineLen + 1 - -proc fits(g: TSrcGen, x: int): bool = - result = x + g.lineLen <= maxLineLen - -type - TSubFlag = enum - rfLongMode, rfNoIndent, rfInConstExpr - TSubFlags = set[TSubFlag] - TContext = tuple[spacing: int, flags: TSubFlags] - -const - emptyContext: TContext = (spacing: 0, flags: {}) - -proc initContext(c: var TContext) = - c.spacing = 0 - c.flags = {} - -proc gsub(g: var TSrcGen, n: PNode, c: TContext) -proc gsub(g: var TSrcGen, n: PNode) = - var c: TContext - initContext(c) - gsub(g, n, c) - -proc hasCom(n: PNode): bool = - result = false - if n == nil: return - if n.comment != nil: return true - case n.kind - of nkEmpty..nkNilLit: nil - else: - for i in countup(0, sonsLen(n) - 1): - if hasCom(n.sons[i]): return true - -proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) = - put(g, kind, s) - put(g, tkSpaces, Space) - -proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0, - theEnd: int = - 1) = - for i in countup(start, sonsLen(n) + theEnd): - var c = i < sonsLen(n) + theEnd - var sublen = lsub(n.sons[i]) + ord(c) - if not fits(g, sublen) and (ind + sublen < maxLineLen): optNL(g, ind) - gsub(g, n.sons[i]) - if c: - putWithSpace(g, tkComma, ",") - if hasCom(n.sons[i]): - gcoms(g) - optNL(g, ind) - -proc gcomma(g: var TSrcGen, n: PNode, c: TContext, start: int = 0, - theEnd: int = - 1) = - var ind: int - if rfInConstExpr in c.flags: - ind = g.indent + indentWidth - else: - ind = g.lineLen - if ind > maxLineLen div 2: ind = g.indent + longIndentWid - gcommaAux(g, n, ind, start, theEnd) - -proc gcomma(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) = - var ind = g.lineLen - if ind > maxLineLen div 2: ind = g.indent + longIndentWid - gcommaAux(g, n, ind, start, theEnd) - -proc gsons(g: var TSrcGen, n: PNode, c: TContext, start: int = 0, - theEnd: int = - 1) = - for i in countup(start, sonsLen(n) + theEnd): gsub(g, n.sons[i], c) - -proc gsection(g: var TSrcGen, n: PNode, c: TContext, kind: TTokType, - k: string) = - if sonsLen(n) == 0: return # empty var sections are possible - putWithSpace(g, kind, k) - gcoms(g) - indentNL(g) - for i in countup(0, sonsLen(n) - 1): - optNL(g) - gsub(g, n.sons[i], c) - gcoms(g) - dedent(g) - -proc longMode(n: PNode, start: int = 0, theEnd: int = - 1): bool = - result = n.comment != nil - if not result: - # check further - for i in countup(start, sonsLen(n) + theEnd): - if (lsub(n.sons[i]) > maxLineLen): - result = true - break - -proc gstmts(g: var TSrcGen, n: PNode, c: TContext) = - if n == nil: return - if (n.kind == nkStmtList) or (n.kind == nkStmtListExpr): - indentNL(g) - for i in countup(0, sonsLen(n) - 1): - optNL(g) - gsub(g, n.sons[i]) - gcoms(g) - dedent(g) - else: - if rfLongMode in c.flags: indentNL(g) - gsub(g, n) - gcoms(g) - optNL(g) - if rfLongMode in c.flags: dedent(g) - -proc gif(g: var TSrcGen, n: PNode) = - var - c: TContext - gsub(g, n.sons[0].sons[0]) - initContext(c) - putWithSpace(g, tkColon, ":") - if longMode(n) or (lsub(n.sons[0].sons[1]) + g.lineLen > maxLineLen): - incl(c.flags, rfLongMode) - gcoms(g) # a good place for comments - gstmts(g, n.sons[0].sons[1], c) - var length = sonsLen(n) - for i in countup(1, length - 1): - optNL(g) - gsub(g, n.sons[i], c) - -proc gwhile(g: var TSrcGen, n: PNode) = - var c: TContext - putWithSpace(g, tkWhile, "while") - gsub(g, n.sons[0]) - putWithSpace(g, tkColon, ":") - initContext(c) - if longMode(n) or (lsub(n.sons[1]) + g.lineLen > maxLineLen): - incl(c.flags, rfLongMode) - gcoms(g) # a good place for comments - gstmts(g, n.sons[1], c) - -proc gtry(g: var TSrcGen, n: PNode) = - var c: TContext - put(g, tkTry, "try") - putWithSpace(g, tkColon, ":") - initContext(c) - if longMode(n) or (lsub(n.sons[0]) + g.lineLen > maxLineLen): - incl(c.flags, rfLongMode) - gcoms(g) # a good place for comments - gstmts(g, n.sons[0], c) - gsons(g, n, c, 1) - -proc gfor(g: var TSrcGen, n: PNode) = - var c: TContext - var length = sonsLen(n) - putWithSpace(g, tkFor, "for") - initContext(c) - if longMode(n) or - (lsub(n.sons[length - 1]) + lsub(n.sons[length - 2]) + 6 + g.lineLen > - maxLineLen): - incl(c.flags, rfLongMode) - gcomma(g, n, c, 0, - 3) - put(g, tkSpaces, Space) - putWithSpace(g, tkIn, "in") - gsub(g, n.sons[length - 2], c) - putWithSpace(g, tkColon, ":") - gcoms(g) - gstmts(g, n.sons[length - 1], c) - -proc gmacro(g: var TSrcGen, n: PNode) = - var c: TContext - initContext(c) - gsub(g, n.sons[0]) - putWithSpace(g, tkColon, ":") - if longMode(n) or (lsub(n.sons[1]) + g.lineLen > maxLineLen): - incl(c.flags, rfLongMode) - gcoms(g) - gsons(g, n, c, 1) - -proc gcase(g: var TSrcGen, n: PNode) = - var c: TContext - initContext(c) - var length = sonsLen(n) - var last = if n.sons[length-1].kind == nkElse: -2 else: -1 - if longMode(n, 0, last): incl(c.flags, rfLongMode) - putWithSpace(g, tkCase, "case") - gsub(g, n.sons[0]) - gcoms(g) - optNL(g) - gsons(g, n, c, 1, last) - if last == - 2: - initContext(c) - if longMode(n.sons[length - 1]): incl(c.flags, rfLongMode) - gsub(g, n.sons[length - 1], c) - -proc gproc(g: var TSrcGen, n: PNode) = - var c: TContext - gsub(g, n.sons[0]) - gsub(g, n.sons[1]) - gsub(g, n.sons[2]) - gsub(g, n.sons[3]) - if not (renderNoBody in g.flags): - if n.sons[4] != nil: - put(g, tkSpaces, Space) - putWithSpace(g, tkEquals, "=") - indentNL(g) - gcoms(g) - dedent(g) - initContext(c) - gstmts(g, n.sons[4], c) - putNL(g) - else: - indentNL(g) - gcoms(g) - dedent(g) - -proc gblock(g: var TSrcGen, n: PNode) = - var c: TContext - initContext(c) - putWithSpace(g, tkBlock, "block") - gsub(g, n.sons[0]) - putWithSpace(g, tkColon, ":") - if longMode(n) or (lsub(n.sons[1]) + g.lineLen > maxLineLen): - incl(c.flags, rfLongMode) - gcoms(g) - gstmts(g, n.sons[1], c) - -proc gasm(g: var TSrcGen, n: PNode) = - putWithSpace(g, tkAsm, "asm") - gsub(g, n.sons[0]) - gcoms(g) - gsub(g, n.sons[1]) - -proc gident(g: var TSrcGen, n: PNode) = - var t: TTokType - var s = atom(n) - if (s[0] in scanner.SymChars): - if (n.kind == nkIdent): - if (n.ident.id < ord(tokKeywordLow) - ord(tkSymbol)) or - (n.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)): - t = tkSymbol - else: - t = TTokType(n.ident.id + ord(tkSymbol)) - else: - t = tkSymbol - else: - t = tkOpr - put(g, t, s) - if (n.kind == nkSym) and (renderIds in g.flags): put(g, tkIntLit, $(n.sym.id)) - -proc gsub(g: var TSrcGen, n: PNode, c: TContext) = - var - L: int - a: TContext - if n == nil: return - if n.comment != nil: pushCom(g, n) - case n.kind # atoms: - of nkTripleStrLit: putRawStr(g, tkTripleStrLit, n.strVal) - of nkEmpty, nkType: put(g, tkInvalid, atom(n)) - of nkSym, nkIdent: gident(g, n) - of nkIntLit: put(g, tkIntLit, atom(n)) - of nkInt8Lit: put(g, tkInt8Lit, atom(n)) - of nkInt16Lit: put(g, tkInt16Lit, atom(n)) - of nkInt32Lit: put(g, tkInt32Lit, atom(n)) - of nkInt64Lit: put(g, tkInt64Lit, atom(n)) - of nkFloatLit: put(g, tkFloatLit, atom(n)) - of nkFloat32Lit: put(g, tkFloat32Lit, atom(n)) - of nkFloat64Lit: put(g, tkFloat64Lit, atom(n)) - of nkStrLit: put(g, tkStrLit, atom(n)) - of nkRStrLit: put(g, tkRStrLit, atom(n)) - of nkCharLit: put(g, tkCharLit, atom(n)) - of nkNilLit: put(g, tkNil, atom(n)) # complex expressions - of nkCall, nkConv, nkDotCall: - if sonsLen(n) >= 1: gsub(g, n.sons[0]) - put(g, tkParLe, "(") - gcomma(g, n, 1) - put(g, tkParRi, ")") - of nkCallStrLit: - gsub(g, n.sons[0]) - if n.sons[1].kind == nkRStrLit: - put(g, tkRStrLit, '\"' & replace(n[1].strVal, "\"", "\"\"") & '\"') - else: - gsub(g, n.sons[0]) - of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: gsub(g, n.sons[0]) - of nkCast: - put(g, tkCast, "cast") - put(g, tkBracketLe, "[") - gsub(g, n.sons[0]) - put(g, tkBracketRi, "]") - put(g, tkParLe, "(") - gsub(g, n.sons[1]) - put(g, tkParRi, ")") - of nkAddr: - put(g, tkAddr, "addr") - put(g, tkParLe, "(") - gsub(g, n.sons[0]) - put(g, tkParRi, ")") - of nkBracketExpr: - gsub(g, n.sons[0]) - put(g, tkBracketLe, "[") - gcomma(g, n, 1) - put(g, tkBracketRi, "]") - of nkPragmaExpr: - gsub(g, n.sons[0]) - gcomma(g, n, 1) - of nkCommand: - gsub(g, n.sons[0]) - put(g, tkSpaces, space) - gcomma(g, n, 1) - of nkExprEqExpr, nkAsgn, nkFastAsgn: - gsub(g, n.sons[0]) - put(g, tkSpaces, Space) - putWithSpace(g, tkEquals, "=") - gsub(g, n.sons[1]) - of nkChckRangeF: - put(g, tkSymbol, "chckRangeF") - put(g, tkParLe, "(") - gcomma(g, n) - put(g, tkParRi, ")") - of nkChckRange64: - put(g, tkSymbol, "chckRange64") - put(g, tkParLe, "(") - gcomma(g, n) - put(g, tkParRi, ")") - of nkChckRange: - put(g, tkSymbol, "chckRange") - put(g, tkParLe, "(") - gcomma(g, n) - put(g, tkParRi, ")") - of nkObjDownConv, nkObjUpConv, nkStringToCString, nkCStringToString, - nkPassAsOpenArray: - if sonsLen(n) >= 1: gsub(g, n.sons[0]) - put(g, tkParLe, "(") - gcomma(g, n, 1) - put(g, tkParRi, ")") - of nkSymChoice: - put(g, tkParLe, "(") - for i in countup(0, sonsLen(n) - 1): - if i > 0: put(g, tkOpr, "|") - gsub(g, n.sons[i], c) - put(g, tkParRi, ")") - of nkPar: - put(g, tkParLe, "(") - gcomma(g, n, c) - put(g, tkParRi, ")") - of nkCurly: - put(g, tkCurlyLe, "{") - gcomma(g, n, c) - put(g, tkCurlyRi, "}") - of nkBracket: - put(g, tkBracketLe, "[") - gcomma(g, n, c) - put(g, tkBracketRi, "]") - of nkDotExpr: - gsub(g, n.sons[0]) - put(g, tkDot, ".") - gsub(g, n.sons[1]) - of nkBind: - putWithSpace(g, tkBind, "bind") - gsub(g, n.sons[0]) - of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref: - gsub(g, n.sons[0]) - of nkLambda: - assert(n.sons[genericParamsPos] == nil) - putWithSpace(g, tkLambda, "lambda") - gsub(g, n.sons[paramsPos]) - gsub(g, n.sons[pragmasPos]) - put(g, tkSpaces, Space) - putWithSpace(g, tkEquals, "=") - gsub(g, n.sons[codePos]) - of nkConstDef, nkIdentDefs: - gcomma(g, n, 0, - 3) - var L = sonsLen(n) - if n.sons[L - 2] != nil: - putWithSpace(g, tkColon, ":") - gsub(g, n.sons[L - 2]) - if n.sons[L - 1] != nil: - put(g, tkSpaces, Space) - putWithSpace(g, tkEquals, "=") - gsub(g, n.sons[L - 1], c) - of nkVarTuple: - put(g, tkParLe, "(") - gcomma(g, n, 0, - 3) - put(g, tkParRi, ")") - put(g, tkSpaces, Space) - putWithSpace(g, tkEquals, "=") - gsub(g, lastSon(n), c) - of nkExprColonExpr: - gsub(g, n.sons[0]) - putWithSpace(g, tkColon, ":") - gsub(g, n.sons[1]) - of nkInfix: - gsub(g, n.sons[1]) - put(g, tkSpaces, Space) - gsub(g, n.sons[0]) # binary operator - if not fits(g, lsub(n.sons[2]) + lsub(n.sons[0]) + 1): - optNL(g, g.indent + longIndentWid) - else: - put(g, tkSpaces, Space) - gsub(g, n.sons[2]) - of nkPrefix: - gsub(g, n.sons[0]) - put(g, tkSpaces, space) - gsub(g, n.sons[1]) - of nkPostfix: - gsub(g, n.sons[1]) - gsub(g, n.sons[0]) - of nkRange: - gsub(g, n.sons[0]) - put(g, tkDotDot, "..") - gsub(g, n.sons[1]) - of nkDerefExpr: - gsub(g, n.sons[0]) - putWithSpace(g, tkHat, "^") - # unfortunately this requires a space, because ^. would be only one operator - of nkAccQuoted: - put(g, tkAccent, "`") - gsub(g, n.sons[0]) - put(g, tkAccent, "`") - of nkIfExpr: - putWithSpace(g, tkIf, "if") - gsub(g, n.sons[0].sons[0]) - putWithSpace(g, tkColon, ":") - gsub(g, n.sons[0].sons[1]) - gsons(g, n, emptyContext, 1) - of nkElifExpr: - putWithSpace(g, tkElif, " elif") - gsub(g, n.sons[0]) - putWithSpace(g, tkColon, ":") - gsub(g, n.sons[1]) - of nkElseExpr: - put(g, tkElse, " else") - putWithSpace(g, tkColon, ":") - gsub(g, n.sons[0]) - of nkTypeOfExpr: - putWithSpace(g, tkType, "type") - gsub(g, n.sons[0]) - of nkRefTy: - putWithSpace(g, tkRef, "ref") - gsub(g, n.sons[0]) - of nkPtrTy: - putWithSpace(g, tkPtr, "ptr") - gsub(g, n.sons[0]) - of nkVarTy: - putWithSpace(g, tkVar, "var") - gsub(g, n.sons[0]) - of nkDistinctTy: - putWithSpace(g, tkDistinct, "distinct") - gsub(g, n.sons[0]) - of nkTypeDef: - gsub(g, n.sons[0]) - gsub(g, n.sons[1]) - put(g, tkSpaces, Space) - if n.sons[2] != nil: - putWithSpace(g, tkEquals, "=") - gsub(g, n.sons[2]) - of nkObjectTy: - putWithSpace(g, tkObject, "object") - gsub(g, n.sons[0]) - gsub(g, n.sons[1]) - gcoms(g) - gsub(g, n.sons[2]) - of nkRecList: - indentNL(g) - for i in countup(0, sonsLen(n) - 1): - optNL(g) - gsub(g, n.sons[i], c) - gcoms(g) - dedent(g) - putNL(g) - of nkOfInherit: - putWithSpace(g, tkOf, "of") - gsub(g, n.sons[0]) - of nkProcTy: - putWithSpace(g, tkProc, "proc") - gsub(g, n.sons[0]) - gsub(g, n.sons[1]) - of nkEnumTy: - putWithSpace(g, tkEnum, "enum") - gsub(g, n.sons[0]) - gcoms(g) - indentNL(g) - gcommaAux(g, n, g.indent, 1) - gcoms(g) # BUGFIX: comment for the last enum field - dedent(g) - of nkEnumFieldDef: - gsub(g, n.sons[0]) - put(g, tkSpaces, Space) - putWithSpace(g, tkEquals, "=") - gsub(g, n.sons[1]) - of nkStmtList, nkStmtListExpr: gstmts(g, n, emptyContext) - of nkIfStmt: - putWithSpace(g, tkIf, "if") - gif(g, n) - of nkWhenStmt, nkRecWhen: - putWithSpace(g, tkWhen, "when") - gif(g, n) - of nkWhileStmt: gwhile(g, n) - of nkCaseStmt, nkRecCase: gcase(g, n) - of nkMacroStmt: gmacro(g, n) - of nkTryStmt: gtry(g, n) - of nkForStmt: gfor(g, n) - of nkBlockStmt, nkBlockExpr: gblock(g, n) - of nkAsmStmt: gasm(g, n) - of nkProcDef: - putWithSpace(g, tkProc, "proc") - gproc(g, n) - of nkMethodDef: - putWithSpace(g, tkMethod, "method") - gproc(g, n) - of nkIteratorDef: - putWithSpace(g, tkIterator, "iterator") - gproc(g, n) - of nkMacroDef: - putWithSpace(g, tkMacro, "macro") - gproc(g, n) - of nkTemplateDef: - putWithSpace(g, tkTemplate, "template") - gproc(g, n) - of nkTypeSection: - gsection(g, n, emptyContext, tkType, "type") - of nkConstSection: - initContext(a) - incl(a.flags, rfInConstExpr) - gsection(g, n, a, tkConst, "const") - of nkVarSection: - L = sonsLen(n) - if L == 0: return - putWithSpace(g, tkVar, "var") - if L > 1: - gcoms(g) - indentNL(g) - for i in countup(0, L - 1): - optNL(g) - gsub(g, n.sons[i]) - gcoms(g) - dedent(g) - else: - gsub(g, n.sons[0]) - of nkReturnStmt: - putWithSpace(g, tkReturn, "return") - gsub(g, n.sons[0]) - of nkRaiseStmt: - putWithSpace(g, tkRaise, "raise") - gsub(g, n.sons[0]) - of nkYieldStmt: - putWithSpace(g, tkYield, "yield") - gsub(g, n.sons[0]) - of nkDiscardStmt: - putWithSpace(g, tkDiscard, "discard") - gsub(g, n.sons[0]) - of nkBreakStmt: - putWithSpace(g, tkBreak, "break") - gsub(g, n.sons[0]) - of nkContinueStmt: - putWithSpace(g, tkContinue, "continue") - gsub(g, n.sons[0]) - of nkPragma: - if not (renderNoPragmas in g.flags): - put(g, tkCurlyDotLe, "{.") - gcomma(g, n, emptyContext) - put(g, tkCurlyDotRi, ".}") - of nkImportStmt: - putWithSpace(g, tkImport, "import") - gcoms(g) - indentNL(g) - gcommaAux(g, n, g.indent) - dedent(g) - putNL(g) - of nkFromStmt: - putWithSpace(g, tkFrom, "from") - gsub(g, n.sons[0]) - put(g, tkSpaces, Space) - putWithSpace(g, tkImport, "import") - gcomma(g, n, emptyContext, 1) - putNL(g) - of nkIncludeStmt: - putWithSpace(g, tkInclude, "include") - gcoms(g) - indentNL(g) - gcommaAux(g, n, g.indent) - dedent(g) - putNL(g) - of nkCommentStmt: - gcoms(g) - optNL(g) - of nkOfBranch: - optNL(g) - putWithSpace(g, tkOf, "of") - gcomma(g, n, c, 0, - 2) - putWithSpace(g, tkColon, ":") - gcoms(g) - gstmts(g, lastSon(n), c) - of nkElifBranch: - optNL(g) - putWithSpace(g, tkElif, "elif") - gsub(g, n.sons[0]) - putWithSpace(g, tkColon, ":") - gcoms(g) - gstmts(g, n.sons[1], c) - of nkElse: - optNL(g) - put(g, tkElse, "else") - putWithSpace(g, tkColon, ":") - gcoms(g) - gstmts(g, n.sons[0], c) - of nkFinally: - optNL(g) - put(g, tkFinally, "finally") - putWithSpace(g, tkColon, ":") - gcoms(g) - gstmts(g, n.sons[0], c) - of nkExceptBranch: - optNL(g) - putWithSpace(g, tkExcept, "except") - gcomma(g, n, 0, - 2) - putWithSpace(g, tkColon, ":") - gcoms(g) - gstmts(g, lastSon(n), c) - of nkGenericParams: - put(g, tkBracketLe, "[") - gcomma(g, n) - put(g, tkBracketRi, "]") - of nkFormalParams: - put(g, tkParLe, "(") - gcomma(g, n, 1) - put(g, tkParRi, ")") - if n.sons[0] != nil: - putWithSpace(g, tkColon, ":") - gsub(g, n.sons[0]) - of nkTupleTy: - put(g, tkTuple, "tuple") - put(g, tkBracketLe, "[") - gcomma(g, n) - put(g, tkBracketRi, "]") - else: - #nkNone, nkMetaNode, nkTableConstr, nkExplicitTypeListCall: - InternalError(n.info, "rnimsyn.gsub(" & $n.kind & ')') - -proc renderTree(n: PNode, renderFlags: TRenderFlags = {}): string = - var g: TSrcGen - initSrcGen(g, renderFlags) - gsub(g, n) - result = g.buf - -proc renderModule(n: PNode, filename: string, renderFlags: TRenderFlags = {}) = - var - f: tfile - g: TSrcGen - initSrcGen(g, renderFlags) - for i in countup(0, sonsLen(n) - 1): - gsub(g, n.sons[i]) - optNL(g) - if n.sons[i] != nil: - case n.sons[i].kind - of nkTypeSection, nkConstSection, nkVarSection, nkCommentStmt: putNL(g) - else: nil - gcoms(g) - if open(f, filename, fmWrite): - write(f, g.buf) - close(f) - -proc initTokRender(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) = - initSrcGen(r, renderFlags) - gsub(r, n) - -proc getNextTok(r: var TSrcGen, kind: var TTokType, literal: var string) = - if r.idx < len(r.tokens): - kind = r.tokens[r.idx].kind - var length = r.tokens[r.idx].length - literal = copy(r.buf, r.pos + 0, r.pos + 0 + length - 1) - inc(r.pos, length) - inc(r.idx) - else: - kind = tkEof - |