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
|
# This file exists to make it overridable via
# patchFile("plugins", "customast.nim", "customast.nim")
## This also serves as a blueprint for a possible implementation.
import "$nim" / compiler / [lineinfos, idents]
when defined(nimPreviewSlimSystem):
import std/assertions
import "$nim" / compiler / nodekinds
export nodekinds
type
PNode* = ref TNode
TNode*{.final, acyclic.} = object
case kind*: TNodeKind
of nkCharLit..nkUInt64Lit:
intVal: BiggestInt
of nkFloatLit..nkFloat128Lit:
floatVal: BiggestFloat
of nkStrLit..nkTripleStrLit:
strVal: string
of nkSym:
discard
of nkIdent:
ident: PIdent
else:
son, next, last: PNode # linked structure instead of a `seq`
info*: TLineInfo
const
bodyPos* = 6
paramsPos* = 3
proc comment*(n: PNode): string =
result = ""
proc `comment=`*(n: PNode, a: string) =
discard "XXX implement me"
proc add*(father, son: PNode) =
assert son != nil
if father.son == nil:
father.son = son
father.last = son
else:
father.last.next = son
father.last = son
template firstSon*(n: PNode): PNode = n.son
template secondSon*(n: PNode): PNode = n.son.next
proc replaceFirstSon*(n, newson: PNode) {.inline.} =
let old = n.son
n.son = newson
newson.next = old
proc replaceSon*(n: PNode; i: int; newson: PNode) =
assert i > 0
assert newson.next == nil
var i = i
var it = n.son
while i > 0:
it = it.next
dec i
let old = it.next
it.next = newson
newson.next = old
template newNodeImpl(info2) =
result = PNode(kind: kind, info: info2)
proc newNode*(kind: TNodeKind): PNode =
## new node with unknown line info, no type, and no children
newNodeImpl(unknownLineInfo)
proc newNode*(kind: TNodeKind, info: TLineInfo): PNode =
## new node with line info, no type, and no children
newNodeImpl(info)
proc newTree*(kind: TNodeKind; info: TLineInfo; child: PNode): PNode =
result = newNode(kind, info)
result.son = child
proc newAtom*(ident: PIdent, info: TLineInfo): PNode =
result = newNode(nkIdent)
result.ident = ident
result.info = info
proc newAtom*(kind: TNodeKind, intVal: BiggestInt, info: TLineInfo): PNode =
result = newNode(kind, info)
result.intVal = intVal
proc newAtom*(kind: TNodeKind, floatVal: BiggestFloat, info: TLineInfo): PNode =
result = newNode(kind, info)
result.floatVal = floatVal
proc newAtom*(kind: TNodeKind; strVal: sink string; info: TLineInfo): PNode =
result = newNode(kind, info)
result.strVal = strVal
proc lastSon*(n: PNode): PNode {.inline.} = n.last
proc setLastSon*(n: PNode, s: PNode) =
assert s.next == nil
n.last = s
if n.son == nil: n.son = s
proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
params,
name, pattern, genericParams,
pragmas, exceptions: PNode): PNode =
result = newNode(kind, info)
result.add name
result.add pattern
result.add genericParams
result.add params
result.add pragmas
result.add exceptions
result.add body
template transitionNodeKindCommon(k: TNodeKind) =
let obj {.inject.} = n[]
n[] = TNode(kind: k, info: obj.info)
# n.comment = obj.comment # shouldn't be needed, the address doesnt' change
proc transitionSonsKind*(n: PNode, kind: range[nkComesFrom..nkTupleConstr]) =
transitionNodeKindCommon(kind)
n.son = obj.son
template hasSon*(n: PNode): bool = n.son != nil
template has2Sons*(n: PNode): bool = n.son != nil and n.son.next != nil
proc isNewStyleConcept*(n: PNode): bool {.inline.} =
assert n.kind == nkTypeClassTy
result = n.firstSon.kind == nkEmpty
|