diff --git a/compiler/ast.nim b/compiler/ast.nim index 446c00f494e7d..2c8f6f4efdef5 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -10,7 +10,7 @@ # abstract syntax tree + symbol table import - lineinfos, hashes, options, ropes, idents, int128 + lineinfos, hashes, options, ropes, idents, int128, tables from strutils import toLowerAscii export int128 @@ -774,7 +774,6 @@ type ident*: PIdent else: sons*: TNodeSeq - comment*: string TStrTable* = object # a table[PIdent] of PSym counter*: int @@ -991,6 +990,22 @@ type TImplication* = enum impUnknown, impNo, impYes +type Gconfig = object + # we put comments in a side channel to avoid increasing `sizeof(TNode)`, which + # reduces memory usage given that `PNode` is the most numerous type. + comments: Table[int, string] # PNode.id => comment + +var gconfig {.threadvar.}: Gconfig + +proc comment*(n: PNode): string = + gconfig.comments.getOrDefault(cast[int](n)) + +proc `comment=`*(n: PNode, a: string) = + if a.len > 0: + gconfig.comments[cast[int](n)] = a + else: + gconfig.comments.del(cast[int](n)) + # BUGFIX: a module is overloadable so that a proc can have the # same name as an imported module. This is necessary because of # the poor naming choices in the standard library. @@ -1644,8 +1659,8 @@ proc copyNode*(src: PNode): PNode = template transitionNodeKindCommon(k: TNodeKind) = let obj {.inject.} = n[] - n[] = TNode(kind: k, typ: obj.typ, info: obj.info, flags: obj.flags, - comment: obj.comment) + n[] = TNode(kind: k, typ: obj.typ, info: obj.info, flags: obj.flags) + # n.comment = obj.comment # shouldn't be needed, the address doesnt' change when defined(useNodeIds): n.id = obj.id diff --git a/compiler/parser.nim b/compiler/parser.nim index 30180e545e5eb..0bc81f5f1eb49 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -176,7 +176,7 @@ proc rawSkipComment(p: var Parser, node: PNode) = else: node.comment.add p.tok.literal else: - node.comment.add p.tok.literal + node.comment = node.comment & p.tok.literal else: parMessage(p, errInternal, "skipComment") getTok(p) @@ -1824,7 +1824,12 @@ proc parseRoutine(p: var Parser, kind: TNodeKind): PNode = if result.comment.len == 0: # proc fn*(a: int): int = a ## foo # => moves comment `foo` to `fn` - swap(result.comment, body[0].comment) + var c1 = result.comment + var c2 = body[0].comment + if c1.len > 0 or c2.len > 0: + swap(c1, c2) + result.comment = c1 + body[0].comment = c2 else: discard # xxx either `assert false` or issue a warning (otherwise we'll never know of this edge case) proc newCommentStmt(p: var Parser): PNode =