renderer.nim 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2013 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # This module implements the renderer of the standard Nim representation.
  10. import
  11. lexer, options, idents, strutils, ast, msgs, lineinfos
  12. type
  13. TRenderFlag* = enum
  14. renderNone, renderNoBody, renderNoComments, renderDocComments,
  15. renderNoPragmas, renderIds, renderNoProcDefs, renderSyms
  16. TRenderFlags* = set[TRenderFlag]
  17. TRenderTok* = object
  18. kind*: TTokType
  19. length*: int16
  20. sym*: PSym
  21. TRenderTokSeq* = seq[TRenderTok]
  22. TSrcGen* = object
  23. indent*: int
  24. lineLen*: int
  25. pos*: int # current position for iteration over the buffer
  26. idx*: int # current token index for iteration over the buffer
  27. tokens*: TRenderTokSeq
  28. buf*: string
  29. pendingNL*: int # negative if not active; else contains the
  30. # indentation value
  31. pendingWhitespace: int
  32. comStack*: seq[PNode] # comment stack
  33. flags*: TRenderFlags
  34. inGenericParams: bool
  35. checkAnon: bool # we're in a context that can contain sfAnon
  36. inPragma: int
  37. when defined(nimpretty):
  38. pendingNewlineCount: int
  39. fid*: FileIndex
  40. config*: ConfigRef
  41. # We render the source code in a two phases: The first
  42. # determines how long the subtree will likely be, the second
  43. # phase appends to a buffer that will be the output.
  44. proc isKeyword*(i: PIdent): bool =
  45. if (i.id >= ord(tokKeywordLow) - ord(tkSymbol)) and
  46. (i.id <= ord(tokKeywordHigh) - ord(tkSymbol)):
  47. result = true
  48. proc renderDefinitionName*(s: PSym, noQuotes = false): string =
  49. ## Returns the definition name of the symbol.
  50. ##
  51. ## If noQuotes is false the symbol may be returned in backticks. This will
  52. ## happen if the name happens to be a keyword or the first character is not
  53. ## part of the SymStartChars set.
  54. let x = s.name.s
  55. if noQuotes or (x[0] in SymStartChars and not renderer.isKeyword(s.name)):
  56. result = x
  57. else:
  58. result = '`' & x & '`'
  59. when not defined(nimpretty):
  60. const
  61. IndentWidth = 2
  62. longIndentWid = IndentWidth * 2
  63. else:
  64. template IndentWidth: untyped = lexer.gIndentationWidth
  65. template longIndentWid: untyped = IndentWidth() * 2
  66. proc minmaxLine(n: PNode): (int, int) =
  67. case n.kind
  68. of nkTripleStrLit:
  69. result = (n.info.line.int, n.info.line.int + countLines(n.strVal))
  70. of nkCommentStmt:
  71. result = (n.info.line.int, n.info.line.int + countLines(n[0].strVal))
  72. else:
  73. result = (n.info.line.int, n.info.line.int)
  74. for i in 0 ..< safeLen(n):
  75. let (currMin, currMax) = minmaxLine(n[i])
  76. if currMin < result[0]: result[0] = currMin
  77. if currMax > result[1]: result[1] = currMax
  78. proc lineDiff(a, b: PNode): int =
  79. result = minmaxLine(b)[0] - minmaxLine(a)[1]
  80. const
  81. MaxLineLen = 80
  82. LineCommentColumn = 30
  83. proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags; config: ConfigRef) =
  84. g.comStack = @[]
  85. g.tokens = @[]
  86. g.indent = 0
  87. g.lineLen = 0
  88. g.pos = 0
  89. g.idx = 0
  90. g.buf = ""
  91. g.flags = renderFlags
  92. g.pendingNL = -1
  93. g.pendingWhitespace = -1
  94. g.inGenericParams = false
  95. g.config = config
  96. proc addTok(g: var TSrcGen, kind: TTokType, s: string; sym: PSym = nil) =
  97. var length = len(g.tokens)
  98. setLen(g.tokens, length + 1)
  99. g.tokens[length].kind = kind
  100. g.tokens[length].length = int16(len(s))
  101. g.tokens[length].sym = sym
  102. add(g.buf, s)
  103. proc addPendingNL(g: var TSrcGen) =
  104. if g.pendingNL >= 0:
  105. when defined(nimpretty):
  106. let newlines = repeat("\n", clamp(g.pendingNewlineCount, 1, 3))
  107. else:
  108. const newlines = "\n"
  109. addTok(g, tkSpaces, newlines & spaces(g.pendingNL))
  110. g.lineLen = g.pendingNL
  111. g.pendingNL = - 1
  112. g.pendingWhitespace = -1
  113. elif g.pendingWhitespace >= 0:
  114. addTok(g, tkSpaces, spaces(g.pendingWhitespace))
  115. g.pendingWhitespace = -1
  116. proc putNL(g: var TSrcGen, indent: int) =
  117. if g.pendingNL >= 0: addPendingNL(g)
  118. else: addTok(g, tkSpaces, "\n")
  119. g.pendingNL = indent
  120. g.lineLen = indent
  121. g.pendingWhitespace = -1
  122. proc previousNL(g: TSrcGen): bool =
  123. result = g.pendingNL >= 0 or (g.tokens.len > 0 and
  124. g.tokens[^1].kind == tkSpaces)
  125. proc putNL(g: var TSrcGen) =
  126. putNL(g, g.indent)
  127. proc optNL(g: var TSrcGen, indent: int) =
  128. g.pendingNL = indent
  129. g.lineLen = indent
  130. when defined(nimpretty): g.pendingNewlineCount = 0
  131. proc optNL(g: var TSrcGen) =
  132. optNL(g, g.indent)
  133. proc optNL(g: var TSrcGen; a, b: PNode) =
  134. g.pendingNL = g.indent
  135. g.lineLen = g.indent
  136. when defined(nimpretty): g.pendingNewlineCount = lineDiff(a, b)
  137. proc indentNL(g: var TSrcGen) =
  138. inc(g.indent, IndentWidth)
  139. g.pendingNL = g.indent
  140. g.lineLen = g.indent
  141. proc dedent(g: var TSrcGen) =
  142. dec(g.indent, IndentWidth)
  143. assert(g.indent >= 0)
  144. if g.pendingNL > IndentWidth:
  145. dec(g.pendingNL, IndentWidth)
  146. dec(g.lineLen, IndentWidth)
  147. proc put(g: var TSrcGen, kind: TTokType, s: string; sym: PSym = nil) =
  148. if kind != tkSpaces:
  149. addPendingNL(g)
  150. if len(s) > 0:
  151. addTok(g, kind, s, sym)
  152. inc(g.lineLen, len(s))
  153. else:
  154. g.pendingWhitespace = s.len
  155. proc putComment(g: var TSrcGen, s: string) =
  156. if s.len == 0: return
  157. var i = 0
  158. let hi = len(s) - 1
  159. var isCode = (len(s) >= 2) and (s[1] != ' ')
  160. var ind = g.lineLen
  161. var com = "## "
  162. while i <= hi:
  163. case s[i]
  164. of '\0':
  165. break
  166. of '\x0D':
  167. put(g, tkComment, com)
  168. com = "## "
  169. inc(i)
  170. if i <= hi and s[i] == '\x0A': inc(i)
  171. optNL(g, ind)
  172. of '\x0A':
  173. put(g, tkComment, com)
  174. com = "## "
  175. inc(i)
  176. optNL(g, ind)
  177. of ' ', '\x09':
  178. add(com, s[i])
  179. inc(i)
  180. else:
  181. # we may break the comment into a multi-line comment if the line
  182. # gets too long:
  183. # compute length of the following word:
  184. var j = i
  185. while j <= hi and s[j] > ' ': inc(j)
  186. if not isCode and (g.lineLen + (j - i) > MaxLineLen):
  187. put(g, tkComment, com)
  188. optNL(g, ind)
  189. com = "## "
  190. while i <= hi and s[i] > ' ':
  191. add(com, s[i])
  192. inc(i)
  193. put(g, tkComment, com)
  194. optNL(g)
  195. proc maxLineLength(s: string): int =
  196. if s.len == 0: return 0
  197. var i = 0
  198. let hi = len(s) - 1
  199. var lineLen = 0
  200. while i <= hi:
  201. case s[i]
  202. of '\0':
  203. break
  204. of '\x0D':
  205. inc(i)
  206. if i <= hi and s[i] == '\x0A': inc(i)
  207. result = max(result, lineLen)
  208. lineLen = 0
  209. of '\x0A':
  210. inc(i)
  211. result = max(result, lineLen)
  212. lineLen = 0
  213. else:
  214. inc(lineLen)
  215. inc(i)
  216. proc putRawStr(g: var TSrcGen, kind: TTokType, s: string) =
  217. var i = 0
  218. let hi = len(s) - 1
  219. var str = ""
  220. while i <= hi:
  221. case s[i]
  222. of '\x0D':
  223. put(g, kind, str)
  224. str = ""
  225. inc(i)
  226. if i <= hi and s[i] == '\x0A': inc(i)
  227. optNL(g, 0)
  228. of '\x0A':
  229. put(g, kind, str)
  230. str = ""
  231. inc(i)
  232. optNL(g, 0)
  233. else:
  234. add(str, s[i])
  235. inc(i)
  236. put(g, kind, str)
  237. proc containsNL(s: string): bool =
  238. for i in countup(0, len(s) - 1):
  239. case s[i]
  240. of '\x0D', '\x0A':
  241. return true
  242. else:
  243. discard
  244. result = false
  245. proc pushCom(g: var TSrcGen, n: PNode) =
  246. var length = len(g.comStack)
  247. setLen(g.comStack, length + 1)
  248. g.comStack[length] = n
  249. proc popAllComs(g: var TSrcGen) =
  250. setLen(g.comStack, 0)
  251. const
  252. Space = " "
  253. proc shouldRenderComment(g: var TSrcGen, n: PNode): bool =
  254. result = false
  255. if n.kind == nkCommentStmt and n[0].strVal.len > 0:
  256. result = (renderNoComments notin g.flags) or
  257. (renderDocComments in g.flags)
  258. proc gcom(g: var TSrcGen, n: PNode) =
  259. assert(n != nil)
  260. if shouldRenderComment(g, n):
  261. if (g.pendingNL < 0) and (len(g.buf) > 0) and (g.buf[len(g.buf)-1] != ' '):
  262. put(g, tkSpaces, Space)
  263. # Before long comments we cannot make sure that a newline is generated,
  264. # because this might be wrong. But it is no problem in practice.
  265. if (g.pendingNL < 0) and (len(g.buf) > 0) and
  266. (g.lineLen < LineCommentColumn):
  267. var ml = maxLineLength(n[0].strVal)
  268. if ml + LineCommentColumn <= MaxLineLen:
  269. put(g, tkSpaces, spaces(LineCommentColumn - g.lineLen))
  270. putComment(g, n[0].strVal) #assert(g.comStack[high(g.comStack)] = n);
  271. proc gcoms(g: var TSrcGen) =
  272. for i in countup(0, high(g.comStack)): gcom(g, g.comStack[i])
  273. popAllComs(g)
  274. proc lsub(g: TSrcGen; n: PNode): int
  275. proc litAux(g: TSrcGen; n: PNode, x: BiggestInt, size: int): string =
  276. proc skip(t: PType): PType =
  277. result = t
  278. while result != nil and result.kind in {tyGenericInst, tyRange, tyVar, tyLent, tyDistinct,
  279. tyOrdinal, tyAlias, tySink}:
  280. result = lastSon(result)
  281. let typ = n.typ.skip
  282. if typ != nil and typ.kind in {tyBool, tyEnum}:
  283. if sfPure in typ.sym.flags:
  284. result = typ.sym.name.s & '.'
  285. let enumfields = typ.n
  286. # we need a slow linear search because of enums with holes:
  287. for e in items(enumfields):
  288. if e.sym.position == x:
  289. result &= e.sym.name.s
  290. return
  291. if nfBase2 in n.flags: result = "0b" & toBin(x, size * 8)
  292. elif nfBase8 in n.flags: result = "0o" & toOct(x, size * 3)
  293. elif nfBase16 in n.flags: result = "0x" & toHex(x, size * 2)
  294. else: result = $x
  295. proc ulitAux(g: TSrcGen; n: PNode, x: BiggestInt, size: int): string =
  296. if nfBase2 in n.flags: result = "0b" & toBin(x, size * 8)
  297. elif nfBase8 in n.flags: result = "0o" & toOct(x, size * 3)
  298. elif nfBase16 in n.flags: result = "0x" & toHex(x, size * 2)
  299. else: result = $x
  300. # XXX proper unsigned output!
  301. proc atom(g: TSrcGen; n: PNode): string =
  302. when defined(nimpretty):
  303. doAssert g.config != nil, "g.config not initialized!"
  304. let comment = if n.info.commentOffsetA < n.info.commentOffsetB:
  305. " " & fileSection(g.config, g.fid, n.info.commentOffsetA, n.info.commentOffsetB)
  306. else:
  307. ""
  308. if n.info.offsetA <= n.info.offsetB:
  309. # for some constructed tokens this can not be the case and we're better
  310. # off to not mess with the offset then.
  311. return fileSection(g.config, g.fid, n.info.offsetA, n.info.offsetB) & comment
  312. var f: float32
  313. case n.kind
  314. of nkEmpty: result = ""
  315. of nkIdent: result = n.ident.s
  316. of nkSym: result = n.sym.name.s
  317. of nkStrLit: result = ""; result.addQuoted(n.strVal)
  318. of nkRStrLit: result = "r\"" & replace(n.strVal, "\"", "\"\"") & '\"'
  319. of nkTripleStrLit: result = "\"\"\"" & n.strVal & "\"\"\""
  320. of nkCharLit:
  321. result = "\'"
  322. result.addEscapedChar(chr(int(n.intVal)));
  323. result.add '\''
  324. of nkIntLit: result = litAux(g, n, n.intVal, 4)
  325. of nkInt8Lit: result = litAux(g, n, n.intVal, 1) & "\'i8"
  326. of nkInt16Lit: result = litAux(g, n, n.intVal, 2) & "\'i16"
  327. of nkInt32Lit: result = litAux(g, n, n.intVal, 4) & "\'i32"
  328. of nkInt64Lit: result = litAux(g, n, n.intVal, 8) & "\'i64"
  329. of nkUIntLit: result = ulitAux(g, n, n.intVal, 4) & "\'u"
  330. of nkUInt8Lit: result = ulitAux(g, n, n.intVal, 1) & "\'u8"
  331. of nkUInt16Lit: result = ulitAux(g, n, n.intVal, 2) & "\'u16"
  332. of nkUInt32Lit: result = ulitAux(g, n, n.intVal, 4) & "\'u32"
  333. of nkUInt64Lit: result = ulitAux(g, n, n.intVal, 8) & "\'u64"
  334. of nkFloatLit:
  335. if n.flags * {nfBase2, nfBase8, nfBase16} == {}: result = $(n.floatVal)
  336. else: result = litAux(g, n, (cast[PInt64](addr(n.floatVal)))[] , 8)
  337. of nkFloat32Lit:
  338. if n.flags * {nfBase2, nfBase8, nfBase16} == {}:
  339. result = $n.floatVal & "\'f32"
  340. else:
  341. f = n.floatVal.float32
  342. result = litAux(g, n, (cast[PInt32](addr(f)))[], 4) & "\'f32"
  343. of nkFloat64Lit:
  344. if n.flags * {nfBase2, nfBase8, nfBase16} == {}:
  345. result = $n.floatVal & "\'f64"
  346. else:
  347. result = litAux(g, n, (cast[PInt64](addr(n.floatVal)))[], 8) & "\'f64"
  348. of nkNilLit: result = "nil"
  349. of nkType:
  350. if (n.typ != nil) and (n.typ.sym != nil): result = n.typ.sym.name.s
  351. else: result = "[type node]"
  352. else:
  353. internalError(g.config, "rnimsyn.atom " & $n.kind)
  354. result = ""
  355. proc lcomma(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): int =
  356. assert(theEnd < 0)
  357. result = 0
  358. for i in countup(start, sonsLen(n) + theEnd):
  359. let param = n.sons[i]
  360. if nfDefaultParam notin param.flags:
  361. inc(result, lsub(g, param))
  362. inc(result, 2) # for ``, ``
  363. if result > 0:
  364. dec(result, 2) # last does not get a comma!
  365. proc lsons(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): int =
  366. assert(theEnd < 0)
  367. result = 0
  368. for i in countup(start, sonsLen(n) + theEnd): inc(result, lsub(g, n.sons[i]))
  369. proc lsub(g: TSrcGen; n: PNode): int =
  370. # computes the length of a tree
  371. if isNil(n): return 0
  372. if n.kind == nkCommentStmt and n[0].strVal.len > 0: return MaxLineLen + 1
  373. case n.kind
  374. of nkEmpty: result = 0
  375. of nkTripleStrLit:
  376. if containsNL(n.strVal): result = MaxLineLen + 1
  377. else: result = len(atom(g, n))
  378. of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
  379. result = len(atom(g, n))
  380. of nkCall, nkBracketExpr, nkCurlyExpr, nkConv, nkPattern, nkObjConstr:
  381. result = lsub(g, n.sons[0]) + lcomma(g, n, 1) + 2
  382. of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(g, n[1])
  383. of nkCast: result = lsub(g, n.sons[0]) + lsub(g, n.sons[1]) + len("cast[]()")
  384. of nkAddr: result = (if n.len>0: lsub(g, n.sons[0]) + len("addr()") else: 4)
  385. of nkStaticExpr: result = lsub(g, n.sons[0]) + len("static_")
  386. of nkHiddenAddr, nkHiddenDeref, nkStringToCString, nkCStringToString: result = lsub(g, n.sons[0])
  387. of nkCommand: result = lsub(g, n.sons[0]) + lcomma(g, n, 1) + 1
  388. of nkExprEqExpr, nkAsgn, nkFastAsgn: result = lsons(g, n) + 3
  389. of nkPar, nkCurly, nkBracket, nkClosure: result = lcomma(g, n) + 2
  390. of nkTupleConstr:
  391. # assume the trailing comma:
  392. result = lcomma(g, n) + 3
  393. of nkArgList: result = lcomma(g, n)
  394. of nkTableConstr:
  395. result = if n.len > 0: lcomma(g, n) + 2 else: len("{:}")
  396. of nkClosedSymChoice, nkOpenSymChoice:
  397. result = lsons(g, n) + len("()") + sonsLen(n) - 1
  398. of nkTupleTy: result = lcomma(g, n) + len("tuple[]")
  399. of nkTupleClassTy: result = len("tuple")
  400. of nkDotExpr: result = lsons(g, n) + 1
  401. of nkBind: result = lsons(g, n) + len("bind_")
  402. of nkBindStmt: result = lcomma(g, n) + len("bind_")
  403. of nkMixinStmt: result = lcomma(g, n) + len("mixin_")
  404. of nkCheckedFieldExpr: result = lsub(g, n.sons[0])
  405. of nkLambda: result = lsons(g, n) + len("proc__=_")
  406. of nkDo: result = lsons(g, n) + len("do__:_")
  407. of nkConstDef, nkIdentDefs:
  408. result = lcomma(g, n, 0, - 3)
  409. var L = sonsLen(n)
  410. if n.sons[L - 2].kind != nkEmpty: result = result + lsub(g, n.sons[L - 2]) + 2
  411. if n.sons[L - 1].kind != nkEmpty: result = result + lsub(g, n.sons[L - 1]) + 3
  412. of nkVarTuple: result = lcomma(g, n, 0, - 3) + len("() = ") + lsub(g, lastSon(n))
  413. of nkChckRangeF: result = len("chckRangeF") + 2 + lcomma(g, n)
  414. of nkChckRange64: result = len("chckRange64") + 2 + lcomma(g, n)
  415. of nkChckRange: result = len("chckRange") + 2 + lcomma(g, n)
  416. of nkObjDownConv, nkObjUpConv:
  417. result = 2
  418. if sonsLen(n) >= 1: result = result + lsub(g, n.sons[0])
  419. result = result + lcomma(g, n, 1)
  420. of nkExprColonExpr: result = lsons(g, n) + 2
  421. of nkInfix: result = lsons(g, n) + 2
  422. of nkPrefix:
  423. result = lsons(g, n)+1+(if n.len > 0 and n.sons[1].kind == nkInfix: 2 else: 0)
  424. of nkPostfix: result = lsons(g, n)
  425. of nkCallStrLit: result = lsons(g, n)
  426. of nkPragmaExpr: result = lsub(g, n.sons[0]) + lcomma(g, n, 1)
  427. of nkRange: result = lsons(g, n) + 2
  428. of nkDerefExpr: result = lsub(g, n.sons[0]) + 2
  429. of nkAccQuoted: result = lsons(g, n) + 2
  430. of nkIfExpr:
  431. result = lsub(g, n.sons[0].sons[0]) + lsub(g, n.sons[0].sons[1]) + lsons(g, n, 1) +
  432. len("if_:_")
  433. of nkElifExpr: result = lsons(g, n) + len("_elif_:_")
  434. of nkElseExpr: result = lsub(g, n.sons[0]) + len("_else:_") # type descriptions
  435. of nkTypeOfExpr: result = (if n.len > 0: lsub(g, n.sons[0]) else: 0)+len("type()")
  436. of nkRefTy: result = (if n.len > 0: lsub(g, n.sons[0])+1 else: 0) + len("ref")
  437. of nkPtrTy: result = (if n.len > 0: lsub(g, n.sons[0])+1 else: 0) + len("ptr")
  438. of nkVarTy: result = (if n.len > 0: lsub(g, n.sons[0])+1 else: 0) + len("var")
  439. of nkDistinctTy:
  440. result = len("distinct") + (if n.len > 0: lsub(g, n.sons[0])+1 else: 0)
  441. if n.len > 1:
  442. result += (if n[1].kind == nkWith: len("_with_") else: len("_without_"))
  443. result += lcomma(g, n[1])
  444. of nkStaticTy: result = (if n.len > 0: lsub(g, n.sons[0]) else: 0) +
  445. len("static[]")
  446. of nkTypeDef: result = lsons(g, n) + 3
  447. of nkOfInherit: result = lsub(g, n.sons[0]) + len("of_")
  448. of nkProcTy: result = lsons(g, n) + len("proc_")
  449. of nkIteratorTy: result = lsons(g, n) + len("iterator_")
  450. of nkSharedTy: result = lsons(g, n) + len("shared_")
  451. of nkEnumTy:
  452. if sonsLen(n) > 0:
  453. result = lsub(g, n.sons[0]) + lcomma(g, n, 1) + len("enum_")
  454. else:
  455. result = len("enum")
  456. of nkEnumFieldDef:
  457. result = lsons(g, n)
  458. if n.lastSon.kind != nkEmpty: inc result, len(" = ")
  459. of nkVarSection, nkLetSection:
  460. if sonsLen(n) > 1: result = MaxLineLen + 1
  461. else: result = lsons(g, n) + len("var_")
  462. of nkUsingStmt:
  463. if sonsLen(n) > 1: result = MaxLineLen + 1
  464. else: result = lsons(g, n) + len("using_")
  465. of nkReturnStmt: result = lsub(g, n.sons[0]) + len("return_")
  466. of nkRaiseStmt: result = lsub(g, n.sons[0]) + len("raise_")
  467. of nkYieldStmt: result = lsub(g, n.sons[0]) + len("yield_")
  468. of nkDiscardStmt: result = lsub(g, n.sons[0]) + len("discard_")
  469. of nkBreakStmt: result = lsub(g, n.sons[0]) + len("break_")
  470. of nkContinueStmt: result = lsub(g, n.sons[0]) + len("continue_")
  471. of nkPragma: result = lcomma(g, n) + 4
  472. of nkCommentStmt: result = len(n[0].strVal)
  473. of nkOfBranch: result = lcomma(g, n, 0, - 2) + lsub(g, lastSon(n)) + len("of_:_")
  474. of nkImportAs: result = lsub(g, n.sons[0]) + len("_as_") + lsub(g, n.sons[1])
  475. of nkElifBranch: result = lsons(g, n) + len("elif_:_")
  476. of nkElse: result = lsub(g, n.sons[0]) + len("else:_")
  477. of nkFinally: result = lsub(g, n.sons[0]) + len("finally:_")
  478. of nkGenericParams: result = lcomma(g, n) + 2
  479. of nkFormalParams:
  480. result = lcomma(g, n, 1) + 2
  481. if n.sons[0].kind != nkEmpty: result = result + lsub(g, n.sons[0]) + 2
  482. of nkExceptBranch:
  483. result = lcomma(g, n, 0, -2) + lsub(g, lastSon(n)) + len("except_:_")
  484. else: result = MaxLineLen + 1
  485. proc fits(g: TSrcGen, x: int): bool =
  486. result = x + g.lineLen <= MaxLineLen
  487. type
  488. TSubFlag = enum
  489. rfLongMode, rfInConstExpr
  490. TSubFlags = set[TSubFlag]
  491. TContext = tuple[spacing: int, flags: TSubFlags]
  492. const
  493. emptyContext: TContext = (spacing: 0, flags: {})
  494. proc initContext(c: var TContext) =
  495. c.spacing = 0
  496. c.flags = {}
  497. proc gsub(g: var TSrcGen, n: PNode, c: TContext)
  498. proc gsub(g: var TSrcGen, n: PNode) =
  499. var c: TContext
  500. initContext(c)
  501. gsub(g, n, c)
  502. proc hasCom(n: PNode): bool =
  503. result = false
  504. if n.isNil: return false
  505. if n.kind == nkCommentStmt and n[0].strVal.len > 0:
  506. return true
  507. case n.kind
  508. of nkEmpty..nkNilLit: discard
  509. else:
  510. for i in countup(0, sonsLen(n) - 1):
  511. if hasCom(n.sons[i]): return true
  512. proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) =
  513. put(g, kind, s)
  514. put(g, tkSpaces, Space)
  515. proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0,
  516. theEnd: int = - 1, separator = tkComma) =
  517. for i in countup(start, sonsLen(n) + theEnd):
  518. var c = i < sonsLen(n) + theEnd
  519. var sublen = lsub(g, n.sons[i]) + ord(c)
  520. if not fits(g, sublen) and (ind + sublen < MaxLineLen): optNL(g, ind)
  521. let oldLen = g.tokens.len
  522. gsub(g, n.sons[i])
  523. if c:
  524. if g.tokens.len > oldLen:
  525. putWithSpace(g, separator, TokTypeToStr[separator])
  526. if hasCom(n.sons[i]):
  527. gcoms(g)
  528. optNL(g, ind)
  529. proc gcomma(g: var TSrcGen, n: PNode, c: TContext, start: int = 0,
  530. theEnd: int = - 1) =
  531. var ind: int
  532. if rfInConstExpr in c.flags:
  533. ind = g.indent + IndentWidth
  534. else:
  535. ind = g.lineLen
  536. if ind > MaxLineLen div 2: ind = g.indent + longIndentWid
  537. gcommaAux(g, n, ind, start, theEnd)
  538. proc gcomma(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) =
  539. var ind = g.lineLen
  540. if ind > MaxLineLen div 2: ind = g.indent + longIndentWid
  541. gcommaAux(g, n, ind, start, theEnd)
  542. proc gsemicolon(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) =
  543. var ind = g.lineLen
  544. if ind > MaxLineLen div 2: ind = g.indent + longIndentWid
  545. gcommaAux(g, n, ind, start, theEnd, tkSemiColon)
  546. proc gsons(g: var TSrcGen, n: PNode, c: TContext, start: int = 0,
  547. theEnd: int = - 1) =
  548. for i in countup(start, sonsLen(n) + theEnd): gsub(g, n.sons[i], c)
  549. proc gsection(g: var TSrcGen, n: PNode, c: TContext, kind: TTokType,
  550. k: string) =
  551. if sonsLen(n) == 0: return # empty var sections are possible
  552. putWithSpace(g, kind, k)
  553. gcoms(g)
  554. indentNL(g)
  555. for i in countup(0, sonsLen(n) - 1):
  556. optNL(g)
  557. gsub(g, n.sons[i], c)
  558. gcoms(g)
  559. dedent(g)
  560. proc longMode(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): bool =
  561. result = n.kind == nkCommentStmt and n[0].strVal.len > 0
  562. if not result:
  563. # check further
  564. for i in countup(start, sonsLen(n) + theEnd):
  565. if (lsub(g, n.sons[i]) > MaxLineLen):
  566. result = true
  567. break
  568. proc gstmts(g: var TSrcGen, n: PNode, c: TContext, doIndent=true) =
  569. if n.kind == nkEmpty: return
  570. if n.kind in {nkStmtList, nkStmtListExpr, nkStmtListType}:
  571. if doIndent: indentNL(g)
  572. let L = n.len
  573. for i in 0 .. L-1:
  574. if i > 0:
  575. optNL(g, n[i-1], n[i])
  576. else:
  577. optNL(g)
  578. if n[i].kind in {nkStmtList, nkStmtListExpr, nkStmtListType}:
  579. gstmts(g, n[i], c, doIndent=false)
  580. else:
  581. gsub(g, n[i])
  582. gcoms(g)
  583. if doIndent: dedent(g)
  584. else:
  585. indentNL(g)
  586. gsub(g, n)
  587. gcoms(g)
  588. dedent(g)
  589. optNL(g)
  590. proc gcond(g: var TSrcGen, n: PNode) =
  591. if n.kind == nkStmtListExpr:
  592. put(g, tkParLe, "(")
  593. gsub(g, n)
  594. if n.kind == nkStmtListExpr:
  595. put(g, tkParRi, ")")
  596. proc gif(g: var TSrcGen, n: PNode) =
  597. var c: TContext
  598. gcond(g, n.sons[0].sons[0])
  599. initContext(c)
  600. putWithSpace(g, tkColon, ":")
  601. if longMode(g, n) or (lsub(g, n.sons[0].sons[1]) + g.lineLen > MaxLineLen):
  602. incl(c.flags, rfLongMode)
  603. gcoms(g) # a good place for comments
  604. gstmts(g, n.sons[0].sons[1], c)
  605. var length = sonsLen(n)
  606. for i in countup(1, length - 1):
  607. optNL(g)
  608. gsub(g, n.sons[i], c)
  609. proc gwhile(g: var TSrcGen, n: PNode) =
  610. var c: TContext
  611. putWithSpace(g, tkWhile, "while")
  612. gcond(g, n.sons[0])
  613. putWithSpace(g, tkColon, ":")
  614. initContext(c)
  615. if longMode(g, n) or (lsub(g, n.sons[1]) + g.lineLen > MaxLineLen):
  616. incl(c.flags, rfLongMode)
  617. gcoms(g) # a good place for comments
  618. gstmts(g, n.sons[1], c)
  619. proc gpattern(g: var TSrcGen, n: PNode) =
  620. var c: TContext
  621. put(g, tkCurlyLe, "{")
  622. initContext(c)
  623. if longMode(g, n) or (lsub(g, n.sons[0]) + g.lineLen > MaxLineLen):
  624. incl(c.flags, rfLongMode)
  625. gcoms(g) # a good place for comments
  626. gstmts(g, n, c)
  627. put(g, tkCurlyRi, "}")
  628. proc gpragmaBlock(g: var TSrcGen, n: PNode) =
  629. var c: TContext
  630. gsub(g, n.sons[0])
  631. putWithSpace(g, tkColon, ":")
  632. initContext(c)
  633. if longMode(g, n) or (lsub(g, n.sons[1]) + g.lineLen > MaxLineLen):
  634. incl(c.flags, rfLongMode)
  635. gcoms(g) # a good place for comments
  636. gstmts(g, n.sons[1], c)
  637. proc gtry(g: var TSrcGen, n: PNode) =
  638. var c: TContext
  639. put(g, tkTry, "try")
  640. putWithSpace(g, tkColon, ":")
  641. initContext(c)
  642. if longMode(g, n) or (lsub(g, n.sons[0]) + g.lineLen > MaxLineLen):
  643. incl(c.flags, rfLongMode)
  644. gcoms(g) # a good place for comments
  645. gstmts(g, n.sons[0], c)
  646. gsons(g, n, c, 1)
  647. proc gfor(g: var TSrcGen, n: PNode) =
  648. var c: TContext
  649. var length = sonsLen(n)
  650. putWithSpace(g, tkFor, "for")
  651. initContext(c)
  652. if longMode(g, n) or
  653. (lsub(g, n.sons[length - 1]) + lsub(g, n.sons[length - 2]) + 6 + g.lineLen >
  654. MaxLineLen):
  655. incl(c.flags, rfLongMode)
  656. gcomma(g, n, c, 0, - 3)
  657. put(g, tkSpaces, Space)
  658. putWithSpace(g, tkIn, "in")
  659. gsub(g, n.sons[length - 2], c)
  660. putWithSpace(g, tkColon, ":")
  661. gcoms(g)
  662. gstmts(g, n.sons[length - 1], c)
  663. proc gcase(g: var TSrcGen, n: PNode) =
  664. var c: TContext
  665. initContext(c)
  666. var length = sonsLen(n)
  667. if length == 0: return
  668. var last = if n.sons[length-1].kind == nkElse: -2 else: -1
  669. if longMode(g, n, 0, last): incl(c.flags, rfLongMode)
  670. putWithSpace(g, tkCase, "case")
  671. gcond(g, n.sons[0])
  672. gcoms(g)
  673. optNL(g)
  674. gsons(g, n, c, 1, last)
  675. if last == - 2:
  676. initContext(c)
  677. if longMode(g, n.sons[length - 1]): incl(c.flags, rfLongMode)
  678. gsub(g, n.sons[length - 1], c)
  679. proc gproc(g: var TSrcGen, n: PNode) =
  680. var c: TContext
  681. if n.sons[namePos].kind == nkSym:
  682. let s = n.sons[namePos].sym
  683. put(g, tkSymbol, renderDefinitionName(s))
  684. if sfGenSym in s.flags:
  685. put(g, tkIntLit, $s.id)
  686. else:
  687. gsub(g, n.sons[namePos])
  688. if n.sons[patternPos].kind != nkEmpty:
  689. gpattern(g, n.sons[patternPos])
  690. let oldInGenericParams = g.inGenericParams
  691. g.inGenericParams = true
  692. if renderNoBody in g.flags and n[miscPos].kind != nkEmpty and
  693. n[miscPos][1].kind != nkEmpty:
  694. gsub(g, n[miscPos][1])
  695. else:
  696. gsub(g, n.sons[genericParamsPos])
  697. g.inGenericParams = oldInGenericParams
  698. gsub(g, n.sons[paramsPos])
  699. if renderNoPragmas notin g.flags:
  700. gsub(g, n.sons[pragmasPos])
  701. if renderNoBody notin g.flags:
  702. if n.sons[bodyPos].kind != nkEmpty:
  703. put(g, tkSpaces, Space)
  704. putWithSpace(g, tkEquals, "=")
  705. indentNL(g)
  706. gcoms(g)
  707. dedent(g)
  708. initContext(c)
  709. gstmts(g, n.sons[bodyPos], c)
  710. putNL(g)
  711. else:
  712. indentNL(g)
  713. gcoms(g)
  714. dedent(g)
  715. proc gTypeClassTy(g: var TSrcGen, n: PNode) =
  716. var c: TContext
  717. initContext(c)
  718. putWithSpace(g, tkConcept, "concept")
  719. gsons(g, n[0], c) # arglist
  720. gsub(g, n[1]) # pragmas
  721. gsub(g, n[2]) # of
  722. gcoms(g)
  723. indentNL(g)
  724. gcoms(g)
  725. gstmts(g, n[3], c)
  726. dedent(g)
  727. proc gblock(g: var TSrcGen, n: PNode) =
  728. var c: TContext
  729. initContext(c)
  730. if n.sons[0].kind != nkEmpty:
  731. putWithSpace(g, tkBlock, "block")
  732. gsub(g, n.sons[0])
  733. else:
  734. put(g, tkBlock, "block")
  735. putWithSpace(g, tkColon, ":")
  736. if longMode(g, n) or ((n.len > 1) and (lsub(g, n.sons[1]) + g.lineLen > MaxLineLen)):
  737. incl(c.flags, rfLongMode)
  738. gcoms(g)
  739. if n.len > 1:
  740. gstmts(g, n.sons[1], c)
  741. proc gstaticStmt(g: var TSrcGen, n: PNode) =
  742. var c: TContext
  743. putWithSpace(g, tkStatic, "static")
  744. putWithSpace(g, tkColon, ":")
  745. initContext(c)
  746. if longMode(g, n) or (lsub(g, n.sons[0]) + g.lineLen > MaxLineLen):
  747. incl(c.flags, rfLongMode)
  748. gcoms(g) # a good place for comments
  749. gstmts(g, n.sons[0], c)
  750. proc gasm(g: var TSrcGen, n: PNode) =
  751. putWithSpace(g, tkAsm, "asm")
  752. gsub(g, n.sons[0])
  753. gcoms(g)
  754. if n.sons.len > 1:
  755. gsub(g, n.sons[1])
  756. proc gident(g: var TSrcGen, n: PNode) =
  757. if g.inGenericParams and n.kind == nkSym:
  758. if sfAnon in n.sym.flags or
  759. (n.typ != nil and tfImplicitTypeParam in n.typ.flags): return
  760. var t: TTokType
  761. var s = atom(g, n)
  762. if s.len > 0 and s[0] in lexer.SymChars:
  763. if n.kind == nkIdent:
  764. if (n.ident.id < ord(tokKeywordLow) - ord(tkSymbol)) or
  765. (n.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)):
  766. t = tkSymbol
  767. else:
  768. t = TTokType(n.ident.id + ord(tkSymbol))
  769. else:
  770. t = tkSymbol
  771. else:
  772. t = tkOpr
  773. put(g, t, s, if n.kind == nkSym and renderSyms in g.flags: n.sym else: nil)
  774. if n.kind == nkSym and (renderIds in g.flags or sfGenSym in n.sym.flags):
  775. when defined(debugMagics):
  776. put(g, tkIntLit, $n.sym.id & $n.sym.magic)
  777. else:
  778. put(g, tkIntLit, $n.sym.id)
  779. proc doParamsAux(g: var TSrcGen, params: PNode) =
  780. if params.len > 1:
  781. put(g, tkParLe, "(")
  782. gsemicolon(g, params, 1)
  783. put(g, tkParRi, ")")
  784. if params.len > 0 and params.sons[0].kind != nkEmpty:
  785. putWithSpace(g, tkOpr, "->")
  786. gsub(g, params.sons[0])
  787. proc gsub(g: var TSrcGen; n: PNode; i: int) =
  788. if i < n.len:
  789. gsub(g, n[i])
  790. else:
  791. put(g, tkOpr, "<<" & $i & "th child missing for " & $n.kind & " >>")
  792. proc isBracket*(n: PNode): bool =
  793. case n.kind
  794. of nkClosedSymChoice, nkOpenSymChoice:
  795. if n.len > 0: result = isBracket(n[0])
  796. of nkSym: result = n.sym.name.s == "[]"
  797. else: result = false
  798. proc skipHiddenNodes(n: PNode): PNode =
  799. result = n
  800. while result != nil:
  801. if result.kind in {nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv} and result.len > 1:
  802. result = result[1]
  803. elif result.kind in {nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref, nkStringToCString, nkCStringToString} and
  804. result.len > 0:
  805. result = result[0]
  806. else: break
  807. proc accentedName(g: var TSrcGen, n: PNode) =
  808. if n == nil: return
  809. let isOperator =
  810. if n.kind == nkIdent and n.ident.s.len > 0 and n.ident.s[0] in OpChars: true
  811. elif n.kind == nkSym and n.sym.name.s.len > 0 and n.sym.name.s[0] in OpChars: true
  812. else: false
  813. if isOperator:
  814. put(g, tkAccent, "`")
  815. gident(g, n)
  816. put(g, tkAccent, "`")
  817. else:
  818. gsub(g, n)
  819. proc infixArgument(g: var TSrcGen, n: PNode, i: int) =
  820. if i >= n.len: return
  821. var needsParenthesis = false
  822. let n_next = n[i].skipHiddenNodes
  823. if n_next.kind == nkInfix:
  824. if n_next[0].kind in {nkSym, nkIdent} and n[0].kind in {nkSym, nkIdent}:
  825. let nextId = if n_next[0].kind == nkSym: n_next[0].sym.name else: n_next[0].ident
  826. let nnId = if n[0].kind == nkSym: n[0].sym.name else: n[0].ident
  827. if getPrecedence(nextId) < getPrecedence(nnId):
  828. needsParenthesis = true
  829. if needsParenthesis:
  830. put(g, tkParLe, "(")
  831. gsub(g, n, i)
  832. if needsParenthesis:
  833. put(g, tkParRi, ")")
  834. proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
  835. if isNil(n): return
  836. var
  837. a: TContext
  838. case n.kind # atoms:
  839. of nkTripleStrLit: put(g, tkTripleStrLit, atom(g, n))
  840. of nkEmpty: discard
  841. of nkType: put(g, tkInvalid, atom(g, n))
  842. of nkSym, nkIdent: gident(g, n)
  843. of nkIntLit: put(g, tkIntLit, atom(g, n))
  844. of nkInt8Lit: put(g, tkInt8Lit, atom(g, n))
  845. of nkInt16Lit: put(g, tkInt16Lit, atom(g, n))
  846. of nkInt32Lit: put(g, tkInt32Lit, atom(g, n))
  847. of nkInt64Lit: put(g, tkInt64Lit, atom(g, n))
  848. of nkUIntLit: put(g, tkUIntLit, atom(g, n))
  849. of nkUInt8Lit: put(g, tkUInt8Lit, atom(g, n))
  850. of nkUInt16Lit: put(g, tkUInt16Lit, atom(g, n))
  851. of nkUInt32Lit: put(g, tkUInt32Lit, atom(g, n))
  852. of nkUInt64Lit: put(g, tkUInt64Lit, atom(g, n))
  853. of nkFloatLit: put(g, tkFloatLit, atom(g, n))
  854. of nkFloat32Lit: put(g, tkFloat32Lit, atom(g, n))
  855. of nkFloat64Lit: put(g, tkFloat64Lit, atom(g, n))
  856. of nkFloat128Lit: put(g, tkFloat128Lit, atom(g, n))
  857. of nkStrLit: put(g, tkStrLit, atom(g, n))
  858. of nkRStrLit: put(g, tkRStrLit, atom(g, n))
  859. of nkCharLit: put(g, tkCharLit, atom(g, n))
  860. of nkNilLit: put(g, tkNil, atom(g, n)) # complex expressions
  861. of nkCall, nkConv, nkDotCall, nkPattern, nkObjConstr:
  862. if n.len > 0 and isBracket(n[0]):
  863. gsub(g, n, 1)
  864. put(g, tkBracketLe, "[")
  865. gcomma(g, n, 2)
  866. put(g, tkBracketRi, "]")
  867. elif n.len > 1 and n.lastSon.kind == nkStmtList:
  868. accentedName(g, n[0])
  869. if n.len > 2:
  870. put(g, tkParLe, "(")
  871. gcomma(g, n, 1, -2)
  872. put(g, tkParRi, ")")
  873. put(g, tkColon, ":")
  874. gsub(g, n, n.len-1)
  875. else:
  876. if sonsLen(n) >= 1: accentedName(g, n[0])
  877. put(g, tkParLe, "(")
  878. gcomma(g, n, 1)
  879. put(g, tkParRi, ")")
  880. of nkCallStrLit:
  881. if n.len > 0: accentedName(g, n[0])
  882. if n.len > 1 and n.sons[1].kind == nkRStrLit:
  883. put(g, tkRStrLit, '\"' & replace(n[1].strVal, "\"", "\"\"") & '\"')
  884. else:
  885. gsub(g, n, 1)
  886. of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv:
  887. if n.len >= 2:
  888. gsub(g, n.sons[1])
  889. else:
  890. put(g, tkSymbol, "(wrong conv)")
  891. of nkCast:
  892. put(g, tkCast, "cast")
  893. put(g, tkBracketLe, "[")
  894. gsub(g, n, 0)
  895. put(g, tkBracketRi, "]")
  896. put(g, tkParLe, "(")
  897. gsub(g, n, 1)
  898. put(g, tkParRi, ")")
  899. of nkAddr:
  900. put(g, tkAddr, "addr")
  901. if n.len > 0:
  902. put(g, tkParLe, "(")
  903. gsub(g, n.sons[0])
  904. put(g, tkParRi, ")")
  905. of nkStaticExpr:
  906. put(g, tkStatic, "static")
  907. put(g, tkSpaces, Space)
  908. gsub(g, n, 0)
  909. of nkBracketExpr:
  910. gsub(g, n, 0)
  911. put(g, tkBracketLe, "[")
  912. gcomma(g, n, 1)
  913. put(g, tkBracketRi, "]")
  914. of nkCurlyExpr:
  915. gsub(g, n, 0)
  916. put(g, tkCurlyLe, "{")
  917. gcomma(g, n, 1)
  918. put(g, tkCurlyRi, "}")
  919. of nkPragmaExpr:
  920. gsub(g, n, 0)
  921. gcomma(g, n, 1)
  922. of nkCommand:
  923. accentedName(g, n[0])
  924. put(g, tkSpaces, Space)
  925. gcomma(g, n, 1)
  926. of nkExprEqExpr, nkAsgn, nkFastAsgn:
  927. gsub(g, n, 0)
  928. put(g, tkSpaces, Space)
  929. putWithSpace(g, tkEquals, "=")
  930. gsub(g, n, 1)
  931. of nkChckRangeF:
  932. put(g, tkSymbol, "chckRangeF")
  933. put(g, tkParLe, "(")
  934. gcomma(g, n)
  935. put(g, tkParRi, ")")
  936. of nkChckRange64:
  937. put(g, tkSymbol, "chckRange64")
  938. put(g, tkParLe, "(")
  939. gcomma(g, n)
  940. put(g, tkParRi, ")")
  941. of nkChckRange:
  942. put(g, tkSymbol, "chckRange")
  943. put(g, tkParLe, "(")
  944. gcomma(g, n)
  945. put(g, tkParRi, ")")
  946. of nkObjDownConv, nkObjUpConv:
  947. if sonsLen(n) >= 1: gsub(g, n.sons[0])
  948. put(g, tkParLe, "(")
  949. gcomma(g, n, 1)
  950. put(g, tkParRi, ")")
  951. of nkClosedSymChoice, nkOpenSymChoice:
  952. if renderIds in g.flags:
  953. put(g, tkParLe, "(")
  954. for i in countup(0, sonsLen(n) - 1):
  955. if i > 0: put(g, tkOpr, "|")
  956. if n.sons[i].kind == nkSym:
  957. let s = n[i].sym
  958. if s.owner != nil:
  959. put g, tkSymbol, n[i].sym.owner.name.s
  960. put g, tkOpr, "."
  961. put g, tkSymbol, n[i].sym.name.s
  962. else:
  963. gsub(g, n.sons[i], c)
  964. put(g, tkParRi, if n.kind == nkOpenSymChoice: "|...)" else: ")")
  965. else:
  966. gsub(g, n, 0)
  967. of nkPar, nkClosure:
  968. put(g, tkParLe, "(")
  969. gcomma(g, n, c)
  970. put(g, tkParRi, ")")
  971. of nkTupleConstr:
  972. put(g, tkParLe, "(")
  973. gcomma(g, n, c)
  974. if n.len == 1: put(g, tkComma, ",")
  975. put(g, tkParRi, ")")
  976. of nkCurly:
  977. put(g, tkCurlyLe, "{")
  978. gcomma(g, n, c)
  979. put(g, tkCurlyRi, "}")
  980. of nkArgList:
  981. gcomma(g, n, c)
  982. of nkTableConstr:
  983. put(g, tkCurlyLe, "{")
  984. if n.len > 0: gcomma(g, n, c)
  985. else: put(g, tkColon, ":")
  986. put(g, tkCurlyRi, "}")
  987. of nkBracket:
  988. put(g, tkBracketLe, "[")
  989. gcomma(g, n, c)
  990. put(g, tkBracketRi, "]")
  991. of nkDotExpr:
  992. gsub(g, n, 0)
  993. put(g, tkDot, ".")
  994. gsub(g, n, 1)
  995. of nkBind:
  996. putWithSpace(g, tkBind, "bind")
  997. gsub(g, n, 0)
  998. of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref, nkStringToCString, nkCStringToString:
  999. gsub(g, n, 0)
  1000. of nkLambda:
  1001. putWithSpace(g, tkProc, "proc")
  1002. gsub(g, n, paramsPos)
  1003. gsub(g, n, pragmasPos)
  1004. put(g, tkSpaces, Space)
  1005. putWithSpace(g, tkEquals, "=")
  1006. gsub(g, n, bodyPos)
  1007. of nkDo:
  1008. putWithSpace(g, tkDo, "do")
  1009. if paramsPos < n.len:
  1010. doParamsAux(g, n.sons[paramsPos])
  1011. gsub(g, n, pragmasPos)
  1012. put(g, tkColon, ":")
  1013. gsub(g, n, bodyPos)
  1014. of nkConstDef, nkIdentDefs:
  1015. gcomma(g, n, 0, -3)
  1016. var L = sonsLen(n)
  1017. if L >= 2 and n.sons[L - 2].kind != nkEmpty:
  1018. putWithSpace(g, tkColon, ":")
  1019. gsub(g, n, L - 2)
  1020. if L >= 1 and n.sons[L - 1].kind != nkEmpty:
  1021. put(g, tkSpaces, Space)
  1022. putWithSpace(g, tkEquals, "=")
  1023. gsub(g, n.sons[L - 1], c)
  1024. of nkVarTuple:
  1025. put(g, tkParLe, "(")
  1026. gcomma(g, n, 0, -3)
  1027. put(g, tkParRi, ")")
  1028. put(g, tkSpaces, Space)
  1029. putWithSpace(g, tkEquals, "=")
  1030. gsub(g, lastSon(n), c)
  1031. of nkExprColonExpr:
  1032. gsub(g, n, 0)
  1033. putWithSpace(g, tkColon, ":")
  1034. gsub(g, n, 1)
  1035. of nkInfix:
  1036. infixArgument(g, n, 1)
  1037. put(g, tkSpaces, Space)
  1038. gsub(g, n, 0) # binary operator
  1039. if n.len == 3 and not fits(g, lsub(g, n.sons[2]) + lsub(g, n.sons[0]) + 1):
  1040. optNL(g, g.indent + longIndentWid)
  1041. else:
  1042. put(g, tkSpaces, Space)
  1043. infixArgument(g, n, 2)
  1044. of nkPrefix:
  1045. gsub(g, n, 0)
  1046. if n.len > 1:
  1047. let opr = if n[0].kind == nkIdent: n[0].ident
  1048. elif n[0].kind == nkSym: n[0].sym.name
  1049. elif n[0].kind in {nkOpenSymChoice, nkClosedSymChoice}: n[0][0].sym.name
  1050. else: nil
  1051. let n_next = skipHiddenNodes(n[1])
  1052. if n_next.kind == nkPrefix or (opr != nil and renderer.isKeyword(opr)):
  1053. put(g, tkSpaces, Space)
  1054. if n_next.kind == nkInfix:
  1055. put(g, tkParLe, "(")
  1056. gsub(g, n.sons[1])
  1057. put(g, tkParRi, ")")
  1058. else:
  1059. gsub(g, n.sons[1])
  1060. of nkPostfix:
  1061. gsub(g, n, 1)
  1062. gsub(g, n, 0)
  1063. of nkExportDoc:
  1064. pushCom(g, n[1])
  1065. gsub(g, n, 0)
  1066. gsub(g, n, 1)
  1067. of nkRange:
  1068. gsub(g, n, 0)
  1069. put(g, tkDotDot, "..")
  1070. gsub(g, n, 1)
  1071. of nkDerefExpr:
  1072. gsub(g, n, 0)
  1073. put(g, tkOpr, "[]")
  1074. of nkAccQuoted:
  1075. put(g, tkAccent, "`")
  1076. if n.len > 0: gsub(g, n.sons[0])
  1077. for i in 1 ..< n.len:
  1078. put(g, tkSpaces, Space)
  1079. gsub(g, n.sons[i])
  1080. put(g, tkAccent, "`")
  1081. of nkIfExpr:
  1082. putWithSpace(g, tkIf, "if")
  1083. if n.len > 0: gcond(g, n.sons[0].sons[0])
  1084. putWithSpace(g, tkColon, ":")
  1085. if n.len > 0: gsub(g, n.sons[0], 1)
  1086. gsons(g, n, emptyContext, 1)
  1087. of nkElifExpr:
  1088. putWithSpace(g, tkElif, " elif")
  1089. gcond(g, n[0])
  1090. putWithSpace(g, tkColon, ":")
  1091. gsub(g, n, 1)
  1092. of nkElseExpr:
  1093. put(g, tkElse, " else")
  1094. putWithSpace(g, tkColon, ":")
  1095. gsub(g, n, 0)
  1096. of nkTypeOfExpr:
  1097. put(g, tkType, "type")
  1098. put(g, tkParLe, "(")
  1099. if n.len > 0: gsub(g, n.sons[0])
  1100. put(g, tkParRi, ")")
  1101. of nkRefTy:
  1102. if sonsLen(n) > 0:
  1103. putWithSpace(g, tkRef, "ref")
  1104. gsub(g, n.sons[0])
  1105. else:
  1106. put(g, tkRef, "ref")
  1107. of nkPtrTy:
  1108. if sonsLen(n) > 0:
  1109. putWithSpace(g, tkPtr, "ptr")
  1110. gsub(g, n.sons[0])
  1111. else:
  1112. put(g, tkPtr, "ptr")
  1113. of nkVarTy:
  1114. if sonsLen(n) > 0:
  1115. putWithSpace(g, tkVar, "var")
  1116. gsub(g, n.sons[0])
  1117. else:
  1118. put(g, tkVar, "var")
  1119. of nkDistinctTy:
  1120. if n.len > 0:
  1121. putWithSpace(g, tkDistinct, "distinct")
  1122. gsub(g, n.sons[0])
  1123. if n.len > 1:
  1124. if n[1].kind == nkWith:
  1125. putWithSpace(g, tkSymbol, " with")
  1126. else:
  1127. putWithSpace(g, tkSymbol, " without")
  1128. gcomma(g, n[1])
  1129. else:
  1130. put(g, tkDistinct, "distinct")
  1131. of nkTypeDef:
  1132. gsub(g, n, 0)
  1133. gsub(g, n, 1)
  1134. put(g, tkSpaces, Space)
  1135. if n.len > 2 and n.sons[2].kind != nkEmpty:
  1136. putWithSpace(g, tkEquals, "=")
  1137. gsub(g, n.sons[2])
  1138. of nkObjectTy:
  1139. if sonsLen(n) > 0:
  1140. putWithSpace(g, tkObject, "object")
  1141. gsub(g, n.sons[0])
  1142. gsub(g, n.sons[1])
  1143. gcoms(g)
  1144. gsub(g, n.sons[2])
  1145. else:
  1146. put(g, tkObject, "object")
  1147. of nkRecList:
  1148. indentNL(g)
  1149. for i in countup(0, sonsLen(n) - 1):
  1150. optNL(g)
  1151. gsub(g, n.sons[i], c)
  1152. gcoms(g)
  1153. dedent(g)
  1154. putNL(g)
  1155. of nkOfInherit:
  1156. putWithSpace(g, tkOf, "of")
  1157. gsub(g, n, 0)
  1158. of nkProcTy:
  1159. if sonsLen(n) > 0:
  1160. putWithSpace(g, tkProc, "proc")
  1161. gsub(g, n, 0)
  1162. gsub(g, n, 1)
  1163. else:
  1164. put(g, tkProc, "proc")
  1165. of nkIteratorTy:
  1166. if sonsLen(n) > 0:
  1167. putWithSpace(g, tkIterator, "iterator")
  1168. gsub(g, n, 0)
  1169. gsub(g, n, 1)
  1170. else:
  1171. put(g, tkIterator, "iterator")
  1172. of nkStaticTy:
  1173. put(g, tkStatic, "static")
  1174. put(g, tkBracketLe, "[")
  1175. if n.len > 0:
  1176. gsub(g, n.sons[0])
  1177. put(g, tkBracketRi, "]")
  1178. of nkEnumTy:
  1179. if sonsLen(n) > 0:
  1180. putWithSpace(g, tkEnum, "enum")
  1181. gsub(g, n.sons[0])
  1182. gcoms(g)
  1183. indentNL(g)
  1184. gcommaAux(g, n, g.indent, 1)
  1185. gcoms(g) # BUGFIX: comment for the last enum field
  1186. dedent(g)
  1187. else:
  1188. put(g, tkEnum, "enum")
  1189. of nkEnumFieldDef:
  1190. gsub(g, n, 0)
  1191. if n[1].kind != nkEmpty:
  1192. put(g, tkSpaces, Space)
  1193. putWithSpace(g, tkEquals, "=")
  1194. gsub(g, n, 1)
  1195. of nkStmtList, nkStmtListExpr, nkStmtListType: gstmts(g, n, emptyContext)
  1196. of nkIfStmt:
  1197. putWithSpace(g, tkIf, "if")
  1198. gif(g, n)
  1199. of nkWhen, nkRecWhen:
  1200. putWithSpace(g, tkWhen, "when")
  1201. gif(g, n)
  1202. of nkWhileStmt: gwhile(g, n)
  1203. of nkPragmaBlock: gpragmaBlock(g, n)
  1204. of nkCaseStmt, nkRecCase: gcase(g, n)
  1205. of nkTryStmt: gtry(g, n)
  1206. of nkForStmt, nkParForStmt: gfor(g, n)
  1207. of nkBlockStmt, nkBlockExpr: gblock(g, n)
  1208. of nkStaticStmt: gstaticStmt(g, n)
  1209. of nkAsmStmt: gasm(g, n)
  1210. of nkProcDef:
  1211. if renderNoProcDefs notin g.flags: putWithSpace(g, tkProc, "proc")
  1212. gproc(g, n)
  1213. of nkFuncDef:
  1214. if renderNoProcDefs notin g.flags: putWithSpace(g, tkFunc, "func")
  1215. gproc(g, n)
  1216. of nkConverterDef:
  1217. if renderNoProcDefs notin g.flags: putWithSpace(g, tkConverter, "converter")
  1218. gproc(g, n)
  1219. of nkMethodDef:
  1220. if renderNoProcDefs notin g.flags: putWithSpace(g, tkMethod, "method")
  1221. gproc(g, n)
  1222. of nkIteratorDef:
  1223. if renderNoProcDefs notin g.flags: putWithSpace(g, tkIterator, "iterator")
  1224. gproc(g, n)
  1225. of nkMacroDef:
  1226. if renderNoProcDefs notin g.flags: putWithSpace(g, tkMacro, "macro")
  1227. gproc(g, n)
  1228. of nkTemplateDef:
  1229. if renderNoProcDefs notin g.flags: putWithSpace(g, tkTemplate, "template")
  1230. gproc(g, n)
  1231. of nkTypeSection:
  1232. gsection(g, n, emptyContext, tkType, "type")
  1233. of nkConstSection:
  1234. initContext(a)
  1235. incl(a.flags, rfInConstExpr)
  1236. gsection(g, n, a, tkConst, "const")
  1237. of nkVarSection, nkLetSection, nkUsingStmt:
  1238. var L = sonsLen(n)
  1239. if L == 0: return
  1240. if n.kind == nkVarSection: putWithSpace(g, tkVar, "var")
  1241. elif n.kind == nkLetSection: putWithSpace(g, tkLet, "let")
  1242. else: putWithSpace(g, tkUsing, "using")
  1243. if L > 1:
  1244. gcoms(g)
  1245. indentNL(g)
  1246. for i in countup(0, L - 1):
  1247. optNL(g)
  1248. gsub(g, n.sons[i])
  1249. gcoms(g)
  1250. dedent(g)
  1251. else:
  1252. gsub(g, n.sons[0])
  1253. of nkReturnStmt:
  1254. putWithSpace(g, tkReturn, "return")
  1255. gsub(g, n, 0)
  1256. of nkRaiseStmt:
  1257. putWithSpace(g, tkRaise, "raise")
  1258. gsub(g, n, 0)
  1259. of nkYieldStmt:
  1260. putWithSpace(g, tkYield, "yield")
  1261. gsub(g, n, 0)
  1262. of nkDiscardStmt:
  1263. putWithSpace(g, tkDiscard, "discard")
  1264. gsub(g, n, 0)
  1265. of nkBreakStmt:
  1266. putWithSpace(g, tkBreak, "break")
  1267. gsub(g, n, 0)
  1268. of nkContinueStmt:
  1269. putWithSpace(g, tkContinue, "continue")
  1270. gsub(g, n, 0)
  1271. of nkPragma:
  1272. if g.inPragma <= 0:
  1273. inc g.inPragma
  1274. #if not previousNL(g):
  1275. put(g, tkSpaces, Space)
  1276. put(g, tkCurlyDotLe, "{.")
  1277. gcomma(g, n, emptyContext)
  1278. put(g, tkCurlyDotRi, ".}")
  1279. dec g.inPragma
  1280. else:
  1281. gcomma(g, n, emptyContext)
  1282. of nkImportStmt, nkExportStmt:
  1283. if n.kind == nkImportStmt:
  1284. putWithSpace(g, tkImport, "import")
  1285. else:
  1286. putWithSpace(g, tkExport, "export")
  1287. gcoms(g)
  1288. indentNL(g)
  1289. gcommaAux(g, n, g.indent)
  1290. dedent(g)
  1291. putNL(g)
  1292. of nkImportExceptStmt, nkExportExceptStmt:
  1293. if n.kind == nkImportExceptStmt:
  1294. putWithSpace(g, tkImport, "import")
  1295. else:
  1296. putWithSpace(g, tkExport, "export")
  1297. gsub(g, n, 0)
  1298. put(g, tkSpaces, Space)
  1299. putWithSpace(g, tkExcept, "except")
  1300. gcommaAux(g, n, g.indent, 1)
  1301. gcoms(g)
  1302. putNL(g)
  1303. of nkFromStmt:
  1304. putWithSpace(g, tkFrom, "from")
  1305. gsub(g, n, 0)
  1306. put(g, tkSpaces, Space)
  1307. putWithSpace(g, tkImport, "import")
  1308. gcomma(g, n, emptyContext, 1)
  1309. putNL(g)
  1310. of nkIncludeStmt:
  1311. putWithSpace(g, tkInclude, "include")
  1312. gcoms(g)
  1313. indentNL(g)
  1314. gcommaAux(g, n, g.indent)
  1315. dedent(g)
  1316. putNL(g)
  1317. of nkCommentStmt:
  1318. pushCom(g, n)
  1319. gcoms(g)
  1320. optNL(g)
  1321. of nkOfBranch:
  1322. optNL(g)
  1323. putWithSpace(g, tkOf, "of")
  1324. gcomma(g, n, c, 0, - 2)
  1325. putWithSpace(g, tkColon, ":")
  1326. gcoms(g)
  1327. gstmts(g, lastSon(n), c)
  1328. of nkImportAs:
  1329. gsub(g, n, 0)
  1330. put(g, tkSpaces, Space)
  1331. putWithSpace(g, tkAs, "as")
  1332. gsub(g, n, 1)
  1333. of nkBindStmt:
  1334. putWithSpace(g, tkBind, "bind")
  1335. gcomma(g, n, c)
  1336. of nkMixinStmt:
  1337. putWithSpace(g, tkMixin, "mixin")
  1338. gcomma(g, n, c)
  1339. of nkElifBranch:
  1340. optNL(g)
  1341. putWithSpace(g, tkElif, "elif")
  1342. gsub(g, n, 0)
  1343. putWithSpace(g, tkColon, ":")
  1344. gcoms(g)
  1345. if n.sons.len > 1:
  1346. gstmts(g, n.sons[1], c)
  1347. of nkElse:
  1348. optNL(g)
  1349. put(g, tkElse, "else")
  1350. putWithSpace(g, tkColon, ":")
  1351. gcoms(g)
  1352. gstmts(g, n.sons[0], c)
  1353. of nkFinally, nkDefer:
  1354. optNL(g)
  1355. if n.kind == nkFinally:
  1356. put(g, tkFinally, "finally")
  1357. else:
  1358. put(g, tkDefer, "defer")
  1359. putWithSpace(g, tkColon, ":")
  1360. gcoms(g)
  1361. gstmts(g, n.sons[0], c)
  1362. of nkExceptBranch:
  1363. optNL(g)
  1364. if n.len != 1:
  1365. putWithSpace(g, tkExcept, "except")
  1366. else:
  1367. put(g, tkExcept, "except")
  1368. gcomma(g, n, 0, -2)
  1369. putWithSpace(g, tkColon, ":")
  1370. gcoms(g)
  1371. gstmts(g, lastSon(n), c)
  1372. of nkGenericParams:
  1373. proc hasExplicitParams(gp: PNode): bool =
  1374. for p in gp:
  1375. if p.typ == nil or tfImplicitTypeParam notin p.typ.flags:
  1376. return true
  1377. return false
  1378. if n.hasExplicitParams:
  1379. put(g, tkBracketLe, "[")
  1380. gsemicolon(g, n)
  1381. put(g, tkBracketRi, "]")
  1382. of nkFormalParams:
  1383. put(g, tkParLe, "(")
  1384. gsemicolon(g, n, 1)
  1385. put(g, tkParRi, ")")
  1386. if n.len > 0 and n.sons[0].kind != nkEmpty:
  1387. putWithSpace(g, tkColon, ":")
  1388. gsub(g, n.sons[0])
  1389. of nkTupleTy:
  1390. put(g, tkTuple, "tuple")
  1391. put(g, tkBracketLe, "[")
  1392. gcomma(g, n)
  1393. put(g, tkBracketRi, "]")
  1394. of nkTupleClassTy:
  1395. put(g, tkTuple, "tuple")
  1396. of nkComesFrom:
  1397. put(g, tkParLe, "(ComesFrom|")
  1398. gsub(g, n, 0)
  1399. put(g, tkParRi, ")")
  1400. of nkGotoState:
  1401. var c: TContext
  1402. initContext c
  1403. putWithSpace g, tkSymbol, "goto"
  1404. gsons(g, n, c)
  1405. of nkState:
  1406. var c: TContext
  1407. initContext c
  1408. putWithSpace g, tkSymbol, "state"
  1409. gsub(g, n[0], c)
  1410. putWithSpace(g, tkColon, ":")
  1411. indentNL(g)
  1412. gsons(g, n, c, 1)
  1413. dedent(g)
  1414. of nkBreakState:
  1415. put(g, tkTuple, "breakstate")
  1416. of nkTypeClassTy:
  1417. gTypeClassTy(g, n)
  1418. else:
  1419. #nkNone, nkExplicitTypeListCall:
  1420. internalError(g.config, n.info, "rnimsyn.gsub(" & $n.kind & ')')
  1421. proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string =
  1422. var g: TSrcGen
  1423. initSrcGen(g, renderFlags, newPartialConfigRef())
  1424. # do not indent the initial statement list so that
  1425. # writeFile("file.nim", repr n)
  1426. # produces working Nim code:
  1427. if n.kind in {nkStmtList, nkStmtListExpr, nkStmtListType}:
  1428. gstmts(g, n, emptyContext, doIndent = false)
  1429. else:
  1430. gsub(g, n)
  1431. result = g.buf
  1432. proc `$`*(n: PNode): string = n.renderTree
  1433. proc renderModule*(n: PNode, infile, outfile: string,
  1434. renderFlags: TRenderFlags = {};
  1435. fid = FileIndex(-1);
  1436. conf: ConfigRef = nil) =
  1437. var
  1438. f: File
  1439. g: TSrcGen
  1440. initSrcGen(g, renderFlags, conf)
  1441. g.fid = fid
  1442. for i in countup(0, sonsLen(n) - 1):
  1443. gsub(g, n.sons[i])
  1444. optNL(g)
  1445. case n.sons[i].kind
  1446. of nkTypeSection, nkConstSection, nkVarSection, nkLetSection,
  1447. nkCommentStmt: putNL(g)
  1448. else: discard
  1449. gcoms(g)
  1450. if open(f, outfile, fmWrite):
  1451. write(f, g.buf)
  1452. close(f)
  1453. else:
  1454. rawMessage(g.config, errGenerated, "cannot open file: " & outfile)
  1455. proc initTokRender*(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) =
  1456. initSrcGen(r, renderFlags, newPartialConfigRef())
  1457. gsub(r, n)
  1458. proc getNextTok*(r: var TSrcGen, kind: var TTokType, literal: var string) =
  1459. if r.idx < len(r.tokens):
  1460. kind = r.tokens[r.idx].kind
  1461. var length = r.tokens[r.idx].length.int
  1462. literal = substr(r.buf, r.pos, r.pos + length - 1)
  1463. inc(r.pos, length)
  1464. inc(r.idx)
  1465. else:
  1466. kind = tkEof
  1467. proc getTokSym*(r: TSrcGen): PSym =
  1468. if r.idx > 0 and r.idx <= len(r.tokens):
  1469. result = r.tokens[r.idx-1].sym
  1470. else:
  1471. result = nil