astyaml.nim 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2012 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # AST YAML printing
  10. import "."/[ast, lineinfos, msgs, options, rodutils]
  11. import std/[intsets, strutils]
  12. proc addYamlString*(res: var string; s: string) =
  13. res.add "\""
  14. for c in s:
  15. case c
  16. of '\0' .. '\x1F', '\x7F' .. '\xFF':
  17. res.add("\\u" & strutils.toHex(ord(c), 4))
  18. of '\"', '\\':
  19. res.add '\\' & c
  20. else:
  21. res.add c
  22. res.add('\"')
  23. proc makeYamlString(s: string): string =
  24. result = ""
  25. result.addYamlString(s)
  26. proc flagsToStr[T](flags: set[T]): string =
  27. if flags == {}:
  28. result = "[]"
  29. else:
  30. result = ""
  31. for x in items(flags):
  32. if result != "":
  33. result.add(", ")
  34. result.addYamlString($x)
  35. result = "[" & result & "]"
  36. proc lineInfoToStr*(conf: ConfigRef; info: TLineInfo): string =
  37. result = "["
  38. result.addYamlString(toFilename(conf, info))
  39. result.addf ", $1, $2]", [toLinenumber(info), toColumn(info)]
  40. proc treeToYamlAux(res: var string; conf: ConfigRef; n: PNode; marker: var IntSet; indent, maxRecDepth: int)
  41. proc symToYamlAux(res: var string; conf: ConfigRef; n: PSym; marker: var IntSet; indent, maxRecDepth: int)
  42. proc typeToYamlAux(res: var string; conf: ConfigRef; n: PType; marker: var IntSet; indent, maxRecDepth: int)
  43. proc symToYamlAux(res: var string; conf: ConfigRef; n: PSym; marker: var IntSet; indent: int; maxRecDepth: int) =
  44. if n == nil:
  45. res.add("null")
  46. elif containsOrIncl(marker, n.id):
  47. res.addYamlString(n.name.s)
  48. else:
  49. let istr = spaces(indent * 4)
  50. res.addf("kind: $1", [makeYamlString($n.kind)])
  51. res.addf("\n$1name: $2", [istr, makeYamlString(n.name.s)])
  52. res.addf("\n$1typ: ", [istr])
  53. res.typeToYamlAux(conf, n.typ, marker, indent + 1, maxRecDepth - 1)
  54. if conf != nil:
  55. # if we don't pass the config, we probably don't care about the line info
  56. res.addf("\n$1info: $2", [istr, lineInfoToStr(conf, n.info)])
  57. if card(n.flags) > 0:
  58. res.addf("\n$1flags: $2", [istr, flagsToStr(n.flags)])
  59. res.addf("\n$1magic: $2", [istr, makeYamlString($n.magic)])
  60. res.addf("\n$1ast: ", [istr])
  61. res.treeToYamlAux(conf, n.ast, marker, indent + 1, maxRecDepth - 1)
  62. res.addf("\n$1options: $2", [istr, flagsToStr(n.options)])
  63. res.addf("\n$1position: $2", [istr, $n.position])
  64. res.addf("\n$1k: $2", [istr, makeYamlString($n.loc.k)])
  65. res.addf("\n$1storage: $2", [istr, makeYamlString($n.loc.storage)])
  66. if card(n.loc.flags) > 0:
  67. res.addf("\n$1flags: $2", [istr, makeYamlString($n.loc.flags)])
  68. res.addf("\n$1r: $2", [istr, n.loc.r])
  69. res.addf("\n$1lode: $2", [istr])
  70. res.treeToYamlAux(conf, n.loc.lode, marker, indent + 1, maxRecDepth - 1)
  71. proc typeToYamlAux(res: var string; conf: ConfigRef; n: PType; marker: var IntSet; indent: int; maxRecDepth: int) =
  72. if n == nil:
  73. res.add("null")
  74. elif containsOrIncl(marker, n.id):
  75. res.addf "\"$1 @$2\"" % [$n.kind, strutils.toHex(cast[uint](n), sizeof(n) * 2)]
  76. else:
  77. let istr = spaces(indent * 4)
  78. res.addf("kind: $2", [istr, makeYamlString($n.kind)])
  79. res.addf("\n$1sym: ")
  80. res.symToYamlAux(conf, n.sym, marker, indent + 1, maxRecDepth - 1)
  81. res.addf("\n$1n: ")
  82. res.treeToYamlAux(conf, n.n, marker, indent + 1, maxRecDepth - 1)
  83. if card(n.flags) > 0:
  84. res.addf("\n$1flags: $2", [istr, flagsToStr(n.flags)])
  85. res.addf("\n$1callconv: $2", [istr, makeYamlString($n.callConv)])
  86. res.addf("\n$1size: $2", [istr, $(n.size)])
  87. res.addf("\n$1align: $2", [istr, $(n.align)])
  88. if n.hasElementType:
  89. res.addf("\n$1sons:")
  90. for a in n.kids:
  91. res.addf("\n - ")
  92. res.typeToYamlAux(conf, a, marker, indent + 1, maxRecDepth - 1)
  93. proc treeToYamlAux(res: var string; conf: ConfigRef; n: PNode; marker: var IntSet; indent: int;
  94. maxRecDepth: int) =
  95. if n == nil:
  96. res.add("null")
  97. else:
  98. var istr = spaces(indent * 4)
  99. res.addf("kind: $1" % [makeYamlString($n.kind)])
  100. if maxRecDepth != 0:
  101. if conf != nil:
  102. res.addf("\n$1info: $2", [istr, lineInfoToStr(conf, n.info)])
  103. case n.kind
  104. of nkCharLit .. nkInt64Lit:
  105. res.addf("\n$1intVal: $2", [istr, $(n.intVal)])
  106. of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
  107. res.addf("\n$1floatVal: $2", [istr, n.floatVal.toStrMaxPrecision])
  108. of nkStrLit .. nkTripleStrLit:
  109. res.addf("\n$1strVal: $2", [istr, makeYamlString(n.strVal)])
  110. of nkSym:
  111. res.addf("\n$1sym: ", [istr])
  112. res.symToYamlAux(conf, n.sym, marker, indent + 1, maxRecDepth)
  113. of nkIdent:
  114. if n.ident != nil:
  115. res.addf("\n$1ident: $2", [istr, makeYamlString(n.ident.s)])
  116. else:
  117. res.addf("\n$1ident: null", [istr])
  118. else:
  119. if n.len > 0:
  120. res.addf("\n$1sons: ", [istr])
  121. for i in 0 ..< n.len:
  122. res.addf("\n$1 - ", [istr])
  123. res.treeToYamlAux(conf, n[i], marker, indent + 1, maxRecDepth - 1)
  124. if n.typ != nil:
  125. res.addf("\n$1typ: ", [istr])
  126. res.typeToYamlAux(conf, n.typ, marker, indent + 1, maxRecDepth)
  127. proc treeToYaml*(conf: ConfigRef; n: PNode; indent: int = 0; maxRecDepth: int = -1): string =
  128. var marker = initIntSet()
  129. result = newStringOfCap(1024)
  130. result.treeToYamlAux(conf, n, marker, indent, maxRecDepth)
  131. proc typeToYaml*(conf: ConfigRef; n: PType; indent: int = 0; maxRecDepth: int = -1): string =
  132. var marker = initIntSet()
  133. result = newStringOfCap(1024)
  134. result.typeToYamlAux(conf, n, marker, indent, maxRecDepth)
  135. proc symToYaml*(conf: ConfigRef; n: PSym; indent: int = 0; maxRecDepth: int = -1): string =
  136. var marker = initIntSet()
  137. result = newStringOfCap(1024)
  138. result.symToYamlAux(conf, n, marker, indent, maxRecDepth)