1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#
#
# The Nimrod Compiler
# (c) Copyright 2008 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
proc getMagic*(op: PNode): TMagic
proc isConstExpr*(n: PNode): bool
proc flattenTree*(root: PNode, op: TMagic): PNode
proc TreeToSym*(t: PNode): PSym
proc SwapOperands*(op: PNode)
proc getOpSym*(op: PNode): PSym
proc getProcSym*(call: PNode): PSym
proc ExprStructuralEquivalent*(a, b: PNode): bool
proc sameTree*(a, b: PNode): bool
proc cyclicTree*(n: PNode): bool
# implementation
proc hasSon(father, son: PNode): bool =
for i in countup(0, sonsLen(father) - 1):
if father.sons[i] == son:
return true
result = false
proc cyclicTreeAux(n, s: PNode): bool =
if n == nil:
return false
if hasSon(s, n):
return true
var m = sonsLen(s)
addSon(s, n)
if not (n.kind in {nkEmpty..nkNilLit}):
for i in countup(0, sonsLen(n) - 1):
if cyclicTreeAux(n.sons[i], s):
return true
result = false
delSon(s, m)
proc cyclicTree(n: PNode): bool =
var s = newNodeI(nkEmpty, n.info)
result = cyclicTreeAux(n, s)
proc ExprStructuralEquivalent(a, b: PNode): bool =
result = false
if a == b:
result = true
elif (a != nil) and (b != nil) and (a.kind == b.kind):
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..nkInt64Lit: 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]): return
result = true
proc sameTree(a, b: PNode): bool =
result = false
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..nkInt64Lit: 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 getProcSym(call: PNode): PSym =
result = call.sons[0].sym
proc getOpSym(op: PNode): PSym =
if not (op.kind in {nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit}):
result = nil
else:
if (sonsLen(op) <= 0): InternalError(op.info, "getOpSym")
if op.sons[0].Kind == nkSym: result = op.sons[0].sym
else: result = nil
proc getMagic(op: PNode): TMagic =
case op.kind
of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit:
case op.sons[0].Kind
of nkSym: result = op.sons[0].sym.magic
else: result = mNone
else: result = mNone
proc TreeToSym(t: PNode): PSym =
result = t.sym
proc isConstExpr(n: PNode): bool =
result = (n.kind in
{nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
nkFloatLit..nkFloat64Lit, nkNilLit}) or (nfAllConst in n.flags)
proc flattenTreeAux(d, a: PNode, op: TMagic) =
if (getMagic(a) == op): # a is a "leaf", so add it:
for i in countup(1, sonsLen(a) - 1): # BUGFIX
flattenTreeAux(d, a.sons[i], op)
else:
addSon(d, copyTree(a))
proc flattenTree(root: PNode, op: TMagic): PNode =
result = copyNode(root)
if (getMagic(root) == op):
# BUGFIX: forget to copy prc
addSon(result, copyNode(root.sons[0]))
flattenTreeAux(result, root, op)
proc SwapOperands(op: PNode) =
var tmp = op.sons[1]
op.sons[1] = op.sons[2]
op.sons[2] = tmp
|