diff options
-rw-r--r-- | compiler/astalgo.nim | 173 | ||||
-rw-r--r-- | compiler/astyaml.nim | 200 |
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) |