# # # The Nim Compiler # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # # tree helper routines import ast, astalgo, lexer, msgs, strutils, wordrecg, idents proc cyclicTreeAux(n: PNode, visited: var seq[PNode]): bool = if n == nil: return for v in visited: if v == n: return true if not (n.kind in {nkEmpty..nkNilLit}): visited.add(n) for nSon in n.sons: if cyclicTreeAux(nSon, visited): return true discard visited.pop() proc cyclicTree*(n: PNode): bool = var visited: seq[PNode] = @[] cyclicTreeAux(n, visited) proc exprStructuralEquivalent*(a, b: PNode; strictSymEquality=false): bool = if a == b: result = true elif (a != nil) and (b != nil) and (a.kind == b.kind): case a.kind of nkSym: if strictSymEquality: result = a.sym == b.sym else: # don't go nuts here: same symbol as string is enough: result = a.sym.name.id == b.sym.name.id of nkIdent: result = a.ident.id == b.ident.id of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal of nkEmpty, nkNilLit, nkType: result = true else: if sonsLen(a) == sonsLen(b): for i in countup(0, sonsLen(a) - 1): if not exprStructuralEquivalent(a.sons[i], b.sons[i], strictSymEquality): return result = true proc sameTree*(a, b: PNode): bool = if a == b: result = true elif a != nil and b != nil and a.kind == b.kind: if a.flags != b.flags: return if a.info.line != b.info.line: return if a.info.col != b.info.col: return #if a.info.fileIndex <> b.info.fileIndex then exit; case a.kind of nkSym: # don't go nuts here: same symbol as string is enough: result = a.sym.name.id == b.sym.name.id of nkIdent: result = a.ident.id == b.ident.id of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal of nkEmpty, nkNilLit, nkType: result = true else: if sonsLen(a) == sonsLen(b): for i in countup(0, sonsLen(a) - 1): if not sameTree(a.sons[i], b.sons[i]): return result = true proc getMagic*(op: PNode): TMagic = case op.kind of nkCallKinds: case op.sons[0].kind of nkSym: result = op.sons[0].sym.magic else: result = mNone else: result = mNone proc isConstExpr*(n: PNode): bool = const atomKinds = {nkCharLit..nkNilLit} # Char, Int, UInt, Str, Float and Nil literals n.kind in atomKinds or nfAllConst in n.flags proc isCaseObj*(n: PNode): bool = if n.kind == nkRecCase: return true for i in 0..