# # # 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, 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 sameFloatIgnoreNan(a, b: BiggestFloat): bool {.inline.} = ## ignores NaN semantics, but ensures 0.0 == -0.0, see #13730 cast[uint64](a) == cast[uint64](b) or a == b 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 = sameFloatIgnoreNan(a.floatVal, b.floatVal) of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal of nkCommentStmt: result = a.comment == b.comment of nkEmpty, nkNilLit, nkType: result = true else: if a.len == b.len: for i in 0.. 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 = sameFloatIgnoreNan(a.floatVal, b.floatVal) of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal of nkEmpty, nkNilLit, nkType: result = true else: if a.len == b.len: for i in 0.. 0: n[0] else: n case key.kind of nkIdent: result = whichKeyword(key.ident) of nkSym: result = whichKeyword(key.sym.name) of nkCast: result = wCast of nkClosedSymChoice, nkOpenSymChoice: result = whichPragma(key[0]) else: result = wInvalid proc isNoSideEffectPragma*(n: PNode): bool = var k = whichPragma(n) if k == wCast: k = whichPragma(n[1]) result = k == wNoSideEffect proc findPragma*(n: PNode, which: TSpecialWord): PNode = if n.kind == nkPragma: for son in n: if whichPragma(son) == which: return son proc effectSpec*(n: PNode, effectType: TSpecialWord): PNode = for i in 0.. ord(cnst.kind == nkObjConstr)