summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/astalgo.nim173
-rw-r--r--compiler/astyaml.nim200
2 files changed, 203 insertions, 170 deletions
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index 238aa6776..0fd13de00 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -12,24 +12,18 @@
 # the data structures here are used in various places of the compiler.
 
 import
-  ast, options, lineinfos, ropes, idents, rodutils,
+  ast, astyaml, options, lineinfos, idents, rodutils,
   msgs
 
 import std/[hashes, intsets]
 import std/strutils except addf
 
+export astyaml.treeToYaml, astyaml.typeToYaml, astyaml.symToYaml, astyaml.lineInfoToStr
+
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
 proc hashNode*(p: RootRef): Hash
-proc treeToYaml*(conf: ConfigRef; n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope
-  # Convert a tree into its YAML representation; this is used by the
-  # YAML code generator and it is invaluable for debugging purposes.
-  # If maxRecDepht <> -1 then it won't print the whole graph.
-proc typeToYaml*(conf: ConfigRef; n: PType, indent: int = 0, maxRecDepth: int = - 1): Rope
-proc symToYaml*(conf: ConfigRef; n: PSym, indent: int = 0, maxRecDepth: int = - 1): Rope
-proc lineInfoToStr*(conf: ConfigRef; info: TLineInfo): Rope
-
 
 # these are for debugging only: They are not really deprecated, but I want
 # the warning so that release versions do not contain debugging statements:
@@ -236,167 +230,6 @@ proc mustRehash(length, counter: int): bool =
   assert(length > counter)
   result = (length * 2 < counter * 3) or (length - counter < 4)
 
-proc rspaces(x: int): Rope =
-  # returns x spaces
-  result = rope(spaces(x))
-
-proc toYamlChar(c: char): string =
-  case c
-  of '\0'..'\x1F', '\x7F'..'\xFF': result = "\\u" & strutils.toHex(ord(c), 4)
-  of '\'', '\"', '\\': result = '\\' & c
-  else: result = $c
-
-proc makeYamlString*(s: string): Rope =
-  # We have to split long strings into many ropes. Otherwise
-  # this could trigger InternalError(111). See the ropes module for
-  # further information.
-  const MaxLineLength = 64
-  result = ""
-  var res = "\""
-  for i in 0..<s.len:
-    if (i + 1) mod MaxLineLength == 0:
-      res.add('\"')
-      res.add("\n")
-      result.add(rope(res))
-      res = "\""              # reset
-    res.add(toYamlChar(s[i]))
-  res.add('\"')
-  result.add(rope(res))
-
-proc flagsToStr[T](flags: set[T]): Rope =
-  if flags == {}:
-    result = rope("[]")
-  else:
-    result = ""
-    for x in items(flags):
-      if result != "": result.add(", ")
-      result.add(makeYamlString($x))
-    result = "[" & result & "]"
-
-proc lineInfoToStr(conf: ConfigRef; info: TLineInfo): Rope =
-  result = "[$1, $2, $3]" % [makeYamlString(toFilename(conf, info)),
-                             rope(toLinenumber(info)),
-                             rope(toColumn(info))]
-
-proc treeToYamlAux(conf: ConfigRef; n: PNode, marker: var IntSet,
-                   indent, maxRecDepth: int): Rope
-proc symToYamlAux(conf: ConfigRef; n: PSym, marker: var IntSet,
-                  indent, maxRecDepth: int): Rope
-proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet,
-                   indent, maxRecDepth: int): Rope
-
-proc symToYamlAux(conf: ConfigRef; n: PSym, marker: var IntSet, indent: int,
-                  maxRecDepth: int): Rope =
-  if n == nil:
-    result = rope("null")
-  elif containsOrIncl(marker, n.id):
-    result = "\"$1\"" % [rope(n.name.s)]
-  else:
-    var ast = treeToYamlAux(conf, n.ast, marker, indent + 2, maxRecDepth - 1)
-                                 #rope("typ"), typeToYamlAux(conf, n.typ, marker,
-                                 #  indent + 2, maxRecDepth - 1),
-    let istr = rspaces(indent + 2)
-    result = rope("{")
-    result.addf("$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
-    result.addf("$N$1\"name\": $2", [istr, makeYamlString(n.name.s)])
-    result.addf("$N$1\"typ\": $2", [istr, typeToYamlAux(conf, n.typ, marker, indent + 2, maxRecDepth - 1)])
-    if conf != nil:
-      # if we don't pass the config, we probably don't care about the line info
-      result.addf("$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
-    if card(n.flags) > 0:
-      result.addf("$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
-    result.addf("$N$1\"magic\": $2", [istr, makeYamlString($n.magic)])
-    result.addf("$N$1\"ast\": $2", [istr, ast])
-    result.addf("$N$1\"options\": $2", [istr, flagsToStr(n.options)])
-    result.addf("$N$1\"position\": $2", [istr, rope(n.position)])
-    result.addf("$N$1\"k\": $2", [istr, makeYamlString($n.loc.k)])
-    result.addf("$N$1\"storage\": $2", [istr, makeYamlString($n.loc.storage)])
-    if card(n.loc.flags) > 0:
-      result.addf("$N$1\"flags\": $2", [istr, makeYamlString($n.loc.flags)])
-    result.addf("$N$1\"r\": $2", [istr, n.loc.r])
-    result.addf("$N$1\"lode\": $2", [istr, treeToYamlAux(conf, n.loc.lode, marker, indent + 2, maxRecDepth - 1)])
-    result.addf("$N$1}", [rspaces(indent)])
-
-proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet, indent: int,
-                   maxRecDepth: int): Rope =
-  var sonsRope: Rope
-  if n == nil:
-    result = ""
-    sonsRope = rope("null")
-  elif containsOrIncl(marker, n.id):
-    result = ""
-    sonsRope = "\"$1 @$2\"" % [rope($n.kind), rope(
-        strutils.toHex(cast[int](n), sizeof(n) * 2))]
-  else:
-    sonsRope = rope("[")
-    for i, a in n.ikids:
-      if i > 0: sonsRope.add(",")
-      sonsRope.addf("$N$1$2", [rspaces(indent + 4), typeToYamlAux(conf, a,
-          marker, indent + 4, maxRecDepth - 1)])
-    sonsRope.addf("$N$1]", [rspaces(indent + 2)])
-
-    let istr = rspaces(indent + 2)
-    result = rope("{")
-    result.addf("$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
-    result.addf("$N$1\"sym\": $2",  [istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth - 1)])
-    result.addf("$N$1\"n\": $2",    [istr, treeToYamlAux(conf, n.n, marker, indent + 2, maxRecDepth - 1)])
-    if card(n.flags) > 0:
-      result.addf("$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
-    result.addf("$N$1\"callconv\": $2", [istr, makeYamlString($n.callConv)])
-    result.addf("$N$1\"size\": $2", [istr, rope(n.size)])
-    result.addf("$N$1\"align\": $2", [istr, rope(n.align)])
-    result.addf("$N$1\"sons\": $2", [istr, sonsRope])
-
-proc treeToYamlAux(conf: ConfigRef; n: PNode, marker: var IntSet, indent: int,
-                   maxRecDepth: int): Rope =
-  if n == nil:
-    result = rope("null")
-  else:
-    var istr = rspaces(indent + 2)
-    result = "{$N$1\"kind\": $2" % [istr, makeYamlString($n.kind)]
-    if maxRecDepth != 0:
-      if conf != nil:
-        result.addf(",$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
-      case n.kind
-      of nkCharLit..nkUInt64Lit:
-        result.addf(",$N$1\"intVal\": $2", [istr, rope(n.intVal)])
-      of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
-        result.addf(",$N$1\"floatVal\": $2",
-            [istr, rope(n.floatVal.toStrMaxPrecision)])
-      of nkStrLit..nkTripleStrLit:
-        result.addf(",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
-      of nkSym:
-        result.addf(",$N$1\"sym\": $2",
-             [istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth)])
-      of nkIdent:
-        if n.ident != nil:
-          result.addf(",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
-        else:
-          result.addf(",$N$1\"ident\": null", [istr])
-      else:
-        if n.len > 0:
-          result.addf(",$N$1\"sons\": [", [istr])
-          for i in 0..<n.len:
-            if i > 0: result.add(",")
-            result.addf("$N$1$2", [rspaces(indent + 4), treeToYamlAux(conf, n[i],
-                marker, indent + 4, maxRecDepth - 1)])
-          result.addf("$N$1]", [istr])
-      result.addf(",$N$1\"typ\": $2",
-           [istr, typeToYamlAux(conf, n.typ, marker, indent + 2, maxRecDepth)])
-    result.addf("$N$1}", [rspaces(indent)])
-
-proc treeToYaml(conf: ConfigRef; n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope =
-  var marker = initIntSet()
-  result = treeToYamlAux(conf, n, marker, indent, maxRecDepth)
-
-proc typeToYaml(conf: ConfigRef; n: PType, indent: int = 0, maxRecDepth: int = - 1): Rope =
-  var marker = initIntSet()
-  result = typeToYamlAux(conf, n, marker, indent, maxRecDepth)
-
-proc symToYaml(conf: ConfigRef; n: PSym, indent: int = 0, maxRecDepth: int = - 1): Rope =
-  var marker = initIntSet()
-  result = symToYamlAux(conf, n, marker, indent, maxRecDepth)
-
 import std/tables
 
 const backrefStyle = "\e[90m"
diff --git a/compiler/astyaml.nim b/compiler/astyaml.nim
new file mode 100644
index 000000000..b098d92b9
--- /dev/null
+++ b/compiler/astyaml.nim
@@ -0,0 +1,200 @@
+#
+#
+#           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$1r: $2", [istr, n.loc.r])
+    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.len > 0:
+      res.addf("\n$1sons:")
+      for i in 0..<n.len:
+        res.addf("\n  - ")
+        res.typeToYamlAux(conf, n[i], 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)