Repository navigation
Expand file tree
/
Copy pathnode.v
More file actions
240 lines (205 loc) · 7.65 KB
/
Copy pathnode.v
File metadata and controls
240 lines (205 loc) · 7.65 KB
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
// To generate example AST JSON, that Node structure maps,
// use clang -w -Xclang -ast-dump=json -fsyntax-only -fno-diagnostics-color -c 1.hello.c > ast.json command, for example.
module main
type Value = string | int | bool
// vfmt off
struct Node {
id string
kind_str string @[json: 'kind'] // e.g. "IntegerLiteral"
previous_declaration string @[json: 'previousDecl']
name string // e.g. "my_var_name"
union_field RefDeclarationNode @[json: 'field'] // selected field in a union initializer
member string @[json: 'member']
referenced_member_decl string @[json: 'referencedMemberDecl']
ast_type AstJsonType @[json: 'type']
ctor_type AstJsonType @[json: 'ctorType']
class_modifier string @[json: 'storageClass']
tags string @[json: 'tagUsed']
value Value @[json: 'value'] // For CharacterLiterals, since `value` is a number there, not at string
opcode string // e.g. "+" in BinaryOperator
mangled_name string @[json: 'mangledName'] // C++ mangled name for methods
cast_kind string @[json: 'castKind'] // e.g. "BitCast" in ImplicitCastExpr
value_category string @[json: 'valueCategory'] // e.g. "lvalue" for reference-returning calls
ast_argument_type AstJsonType @[json: 'argType']
bases []CxxBaseSpecifier @[json: 'bases']
declaration_id string @[json: 'declId'] // for goto labels
label_id string @[json: 'targetLabelDeclId'] // for goto statements
is_postfix bool @[json: 'isPostfix']
is_implicit bool @[json: 'isImplicit']
is_used bool @[json: 'isUsed']
is_pure bool @[json: 'pure']
is_virtual bool @[json: 'virtual']
is_array bool @[json: 'isArray'] // `delete[]` / `new T[n]`
is_arrow bool @[json: 'isArrow'] // a MemberExpr accessed with `->`
complete_definition bool @[json: 'completeDefinition']
is_inline bool @[json: 'inline']
is_referenced bool @[json: 'isReferenced']
is_elidable bool @[json: 'elidable'] // a copy/move construction C++ elides
is_nrvo bool @[json: 'nrvo'] // a local constructed directly in the return slot
parent_decl_context_id string @[json: 'parentDeclContextId'] // set on out-of-line member definitions
explicitly_defaulted string @[json: 'explicitlyDefaulted']
explicitly_deleted bool @[json: 'explicitlyDeleted']
mut:
initialization_type string @[json: 'init'] // "c" => "cinit"
//parent_node &Node [skip] = unsafe {nil }
location NodeLocation @[json: 'loc']
comment string @[skip] // comment string before this node
unique_id int = -1 @[skip]
range Range
inner []Node
array_filler []Node // for InitListExpr
ref_declaration RefDeclarationNode @[json: 'referencedDecl'] //&Node
any_init RefDeclarationNode @[json: 'anyInit']
base_init AstJsonType @[json: 'baseInit'] // the base class a constructor initializer constructs
template_argument_decl RefDeclarationNode @[json: 'decl']
kind NodeKind @[skip]
current_child_id int @[skip]
redeclarations_count int @[skip] // increased when some *other* Node had previous_decl == this Node.id
owned_tag_decl OwnedTagDecl @[json: 'ownedTagDecl'] // for TagDecl nodes, to store the TagDecl node that is owned by this node
}
// vfmt on
struct NodeLocation {
mut:
offset int
file string @[json: 'file']
line int
col int
source_file SourceFile @[json: 'includedFrom']
spelling_file SourceFile @[json: 'spellingLoc']
expansion_file SourceFile @[json: 'expansionLoc']
file_index int = -1
}
struct Range {
mut:
begin Begin
end End
}
struct Begin {
mut:
offset int
line int
col int
file string @[json: 'file']
spelling_file SourceFile @[json: 'spellingLoc']
expansion_file SourceFile @[json: 'expansionLoc']
}
struct End {
mut:
offset int
col int @[json: 'col']
tok_len int @[json: 'tokLen']
file string @[json: 'file']
spelling_file SourceFile @[json: 'spellingLoc']
expansion_file SourceFile @[json: 'expansionLoc']
}
struct SourceFile {
offset int @[json: 'offset']
path string @[json: 'file']
line int
col int
is_macro_arg_expansion bool @[json: 'isMacroArgExpansion']
included_from IncludedFrom @[json: 'includedFrom']
}
struct IncludedFrom {
path string @[json: 'file']
}
struct AstJsonType {
desugared_qualified string @[json: 'desugaredQualType']
qualified string @[json: 'qualType']
}
struct CxxBaseSpecifier {
access string
written_access string @[json: 'writtenAccess']
ast_type AstJsonType @[json: 'type']
}
struct RefDeclarationNode {
id string
kind_str string @[json: 'kind'] // e.g. "IntegerLiteral"
name string
ast_type AstJsonType @[json: 'type']
mut:
kind NodeKind @[skip]
}
struct OwnedTagDecl {
id string
kind_str string @[json: 'kind']
name string
}
const bad_node = Node{
kind: .bad
}
fn (value Value) to_str() string {
if value is int {
return value.str()
} else if value is bool {
return if value { 'true' } else { 'false' }
} else {
return value as string
}
}
fn (node Node) kindof(expected_kind NodeKind) bool {
return node.kind == expected_kind
}
fn (node Node) has_child_of_kind(expected_kind NodeKind) bool {
for child in node.inner {
if child.kindof(expected_kind) {
return true
}
}
return false
}
fn (node Node) count_children_of_kind(kind_filter NodeKind) int {
mut count := 0
for child in node.inner {
if child.kindof(kind_filter) {
count++
}
}
return count
}
fn (node Node) find_children(wanted_kind NodeKind) []Node {
mut suitable_children := []Node{}
if node.inner.len == 0 {
return suitable_children
}
for child in node.inner {
if child.kindof(wanted_kind) {
suitable_children << child
}
}
return suitable_children
}
fn (mut node Node) try_get_next_child_of_kind(wanted_kind NodeKind) !Node {
if node.current_child_id >= node.inner.len {
return error('No more children')
}
mut current_child := node.inner[node.current_child_id]
if current_child.kindof(wanted_kind) == false {
error('try_get_next_child_of_kind(): WANTED ${wanted_kind.str()} BUT GOT ${current_child.kind.str()}')
}
node.current_child_id++
return current_child
}
fn (mut node Node) try_get_next_child() !Node {
if node.current_child_id >= node.inner.len {
return error('No more children')
}
current_child := node.inner[node.current_child_id]
node.current_child_id++
return current_child
}
fn (mut node Node) initialize_node_and_children() {
node.kind = convert_str_into_node_kind(node.kind_str)
if node.ref_declaration.kind_str != '' {
node.ref_declaration.kind = convert_str_into_node_kind(node.ref_declaration.kind_str)
}
if node.any_init.kind_str != '' {
node.any_init.kind = convert_str_into_node_kind(node.any_init.kind_str)
}
if node.template_argument_decl.kind_str != '' {
node.template_argument_decl.kind = convert_str_into_node_kind(node.template_argument_decl.kind_str)
}
for mut child in node.inner {
child.initialize_node_and_children()
}
}