summary refs log tree commit diff stats
path: root/compiler/astyaml.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/astyaml.nim')
-rw-r--r--compiler/astyaml.nim154
1 files changed, 154 insertions, 0 deletions
diff --git a/compiler/astyaml.nim b/compiler/astyaml.nim
new file mode 100644
index 000000000..b0fa2bfb2
--- /dev/null
+++ b/compiler/astyaml.nim
@@ -0,0 +1,154 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2012 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+# AST YAML printing
+
+import "."/[ast, lineinfos, msgs, options, rodutils]
+import std/[intsets, strutils]
+
+proc addYamlString*(res: var string; s: string) =
+  res.add "\""
+  for c in s:
+    case c
+    of '\0' .. '\x1F', '\x7F' .. '\xFF':
+      res.add("\\u" & strutils.toHex(ord(c), 4))
+    of '\"', '\\':
+      res.add '\\' & c
+    else:
+      res.add c
+
+  res.add('\"')
+
+proc makeYamlString(s: string): string =
+  result = ""
+  result.addYamlString(s)
+
+proc flagsToStr[T](flags: set[T]): string =
+  if flags == {}:
+    result = "[]"
+  else:
+    result = ""
+    for x in items(flags):
+      if result != "":
+        result.add(", ")
+      result.addYamlString($x)
+    result = "[" & result & "]"
+
+proc lineInfoToStr*(conf: ConfigRef; info: TLineInfo): string =
+  result = "["
+  result.addYamlString(toFilename(conf, info))
+  result.addf ", $1, $2]", [toLinenumber(info), toColumn(info)]
+
+proc treeToYamlAux(res: var string; conf: ConfigRef; n: PNode; marker: var IntSet; indent, maxRecDepth: int)
+proc symToYamlAux(res: var string; conf: ConfigRef; n: PSym; marker: var IntSet; indent, maxRecDepth: int)
+proc typeToYamlAux(res: var string; conf: ConfigRef; n: PType; marker: var IntSet; indent, maxRecDepth: int)
+
+proc symToYamlAux(res: var string; conf: ConfigRef; n: PSym; marker: var IntSet; indent: int; maxRecDepth: int) =
+  if n == nil:
+    res.add("null")
+  elif containsOrIncl(marker, n.id):
+    res.addYamlString(n.name.s)
+  else:
+    let istr = spaces(indent * 4)
+
+    res.addf("kind: $1", [makeYamlString($n.kind)])
+    res.addf("\n$1name: $2", [istr, makeYamlString(n.name.s)])
+    res.addf("\n$1typ: ", [istr])
+    res.typeToYamlAux(conf, n.typ, marker, indent + 1, maxRecDepth - 1)
+    if conf != nil:
+      # if we don't pass the config, we probably don't care about the line info
+      res.addf("\n$1info: $2", [istr, lineInfoToStr(conf, n.info)])
+    if card(n.flags) > 0:
+      res.addf("\n$1flags: $2", [istr, flagsToStr(n.flags)])
+    res.addf("\n$1magic: $2", [istr, makeYamlString($n.magic)])
+    res.addf("\n$1ast: ", [istr])
+    res.treeToYamlAux(conf, n.ast, marker, indent + 1, maxRecDepth - 1)
+    res.addf("\n$1options: $2", [istr, flagsToStr(n.options)])
+    res.addf("\n$1position: $2", [istr, $n.position])
+    res.addf("\n$1k: $2", [istr, makeYamlString($n.loc.k)])
+    res.addf("\n$1storage: $2", [istr, makeYamlString($n.loc.storage)])
+    if card(n.loc.flags) > 0:
+      res.addf("\n$1flags: $2", [istr, makeYamlString($n.loc.flags)])
+    res.addf("\n$1snippet: $2", [istr, n.loc.snippet])
+    res.addf("\n$1lode: $2", [istr])
+    res.treeToYamlAux(conf, n.loc.lode, marker, indent + 1, maxRecDepth - 1)
+
+proc typeToYamlAux(res: var string; conf: ConfigRef; n: PType; marker: var IntSet; indent: int; maxRecDepth: int) =
+  if n == nil:
+    res.add("null")
+  elif containsOrIncl(marker, n.id):
+    res.addf "\"$1 @$2\"" % [$n.kind, strutils.toHex(cast[uint](n), sizeof(n) * 2)]
+  else:
+    let istr = spaces(indent * 4)
+    res.addf("kind: $2", [istr, makeYamlString($n.kind)])
+    res.addf("\n$1sym: ")
+    res.symToYamlAux(conf, n.sym, marker, indent + 1, maxRecDepth - 1)
+    res.addf("\n$1n: ")
+    res.treeToYamlAux(conf, n.n, marker, indent + 1, maxRecDepth - 1)
+    if card(n.flags) > 0:
+      res.addf("\n$1flags: $2", [istr, flagsToStr(n.flags)])
+    res.addf("\n$1callconv: $2", [istr, makeYamlString($n.callConv)])
+    res.addf("\n$1size: $2", [istr, $(n.size)])
+    res.addf("\n$1align: $2", [istr, $(n.align)])
+    if n.hasElementType:
+      res.addf("\n$1sons:")
+      for a in n.kids:
+        res.addf("\n  - ")
+        res.typeToYamlAux(conf, a, marker, indent + 1, maxRecDepth - 1)
+
+proc treeToYamlAux(res: var string; conf: ConfigRef; n: PNode; marker: var IntSet; indent: int;
+                   maxRecDepth: int) =
+  if n == nil:
+    res.add("null")
+  else:
+    var istr = spaces(indent * 4)
+    res.addf("kind: $1" % [makeYamlString($n.kind)])
+
+    if maxRecDepth != 0:
+      if conf != nil:
+        res.addf("\n$1info: $2", [istr, lineInfoToStr(conf, n.info)])
+      case n.kind
+      of nkCharLit .. nkInt64Lit:
+        res.addf("\n$1intVal: $2", [istr, $(n.intVal)])
+      of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
+        res.addf("\n$1floatVal: $2", [istr, n.floatVal.toStrMaxPrecision])
+      of nkStrLit .. nkTripleStrLit:
+        res.addf("\n$1strVal: $2", [istr, makeYamlString(n.strVal)])
+      of nkSym:
+        res.addf("\n$1sym: ", [istr])
+        res.symToYamlAux(conf, n.sym, marker, indent + 1, maxRecDepth)
+      of nkIdent:
+        if n.ident != nil:
+          res.addf("\n$1ident: $2", [istr, makeYamlString(n.ident.s)])
+        else:
+          res.addf("\n$1ident: null", [istr])
+      else:
+        if n.len > 0:
+          res.addf("\n$1sons: ", [istr])
+          for i in 0 ..< n.len:
+            res.addf("\n$1  - ", [istr])
+            res.treeToYamlAux(conf, n[i], marker, indent + 1, maxRecDepth - 1)
+      if n.typ != nil:
+        res.addf("\n$1typ: ", [istr])
+        res.typeToYamlAux(conf, n.typ, marker, indent + 1, maxRecDepth)
+
+proc treeToYaml*(conf: ConfigRef; n: PNode; indent: int = 0; maxRecDepth: int = -1): string =
+  var marker = initIntSet()
+  result = newStringOfCap(1024)
+  result.treeToYamlAux(conf, n, marker, indent, maxRecDepth)
+
+proc typeToYaml*(conf: ConfigRef; n: PType; indent: int = 0; maxRecDepth: int = -1): string =
+  var marker = initIntSet()
+  result = newStringOfCap(1024)
+  result.typeToYamlAux(conf, n, marker, indent, maxRecDepth)
+
+proc symToYaml*(conf: ConfigRef; n: PSym; indent: int = 0; maxRecDepth: int = -1): string =
+  var marker = initIntSet()
+  result = newStringOfCap(1024)
+  result.symToYamlAux(conf, n, marker, indent, maxRecDepth)