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
|
#
#
# The Nimrod Compiler
# (c) Copyright 2011 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
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, nkPrefix, nkPostfix,
nkInfix:
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
proc IsRange*(n: PNode): bool {.inline.} =
if n.kind == nkInfix:
if n[0].kind == nkIdent and n[0].ident.id == ord(wDotDot) or
n[0].kind == nkSymChoice and n[0][1].sym.name.id == ord(wDotDot):
result = true
|