vxx2 / vlib / v3 / flat / flat.v
336 lines · 312 sloc · 6.35 KB · 288feee4702b35beadb4037d02b96b5c8674156b
Raw
1module flat
2
3import v3.token
4
5// NodeId aliases node id values used by flat.
6pub type NodeId = int
7
8pub const empty_node = NodeId(-1)
9
10const empty_node_value = Node{}
11
12// NodeKind lists node kind values used by flat.
13pub enum NodeKind {
14 empty
15 // expressions
16 int_literal
17 float_literal
18 bool_literal
19 char_literal
20 string_literal
21 string_interp
22 ident
23 infix
24 prefix
25 postfix
26 paren
27 call
28 selector
29 index
30 if_expr
31 struct_init
32 field_init
33 array_literal
34 array_init
35 map_init
36 fn_literal
37 or_expr
38 cast_expr
39 as_expr
40 enum_val
41 assoc
42 range
43 nil_literal
44 none_expr
45 spawn_expr
46 lock_expr
47 lambda_expr
48 sizeof_expr
49 typeof_expr
50 dump_expr
51 offsetof_expr
52 is_expr
53 in_expr
54 // statements
55 expr_stmt
56 assign
57 decl_assign
58 selector_assign
59 index_assign
60 return_stmt
61 block
62 for_stmt
63 for_in_stmt
64 break_stmt
65 continue_stmt
66 match_stmt
67 match_branch
68 defer_stmt
69 assert_stmt
70 goto_stmt
71 label_stmt
72 select_stmt
73 select_branch
74 comptime_if
75 comptime_for
76 asm_stmt
77 // declarations
78 fn_decl
79 struct_decl
80 field_decl
81 global_decl
82 const_decl
83 const_field
84 enum_decl
85 enum_field
86 type_decl
87 interface_decl
88 interface_field
89 import_decl
90 module_decl
91 directive
92 param
93 c_fn_decl
94 // top-level
95 file
96 sql_expr
97}
98
99// Op lists op values used by flat.
100pub enum Op {
101 none
102 plus
103 minus
104 mul
105 div
106 mod
107 eq
108 ne
109 lt
110 gt
111 le
112 ge
113 amp
114 pipe
115 xor
116 left_shift
117 right_shift
118 right_shift_unsigned
119 logical_and
120 logical_or
121 not
122 bit_not
123 assign
124 plus_assign
125 minus_assign
126 mul_assign
127 div_assign
128 mod_assign
129 amp_assign
130 pipe_assign
131 xor_assign
132 left_shift_assign
133 right_shift_assign
134 right_shift_unsigned_assign
135 inc
136 dec
137 dot
138 arrow
139}
140
141// Node represents node data used by flat.
142pub struct Node {
143pub mut:
144 value string
145 typ string
146 generic_params []string
147 kind_id int
148pub:
149 pos token.Pos
150 children_start i32
151 children_count i16
152 kind NodeKind
153 op Op
154}
155
156// FlatAst represents flat ast data used by flat.
157@[heap]
158pub struct FlatAst {
159pub mut:
160 nodes []Node
161 children []NodeId
162 user_code_start int
163 disabled_fns map[string]bool
164 export_fn_names map[string]string
165}
166
167// new creates a FlatAst value for flat.
168pub fn FlatAst.new() FlatAst {
169 return FlatAst{
170 nodes: []Node{cap: 256}
171 children: []NodeId{cap: 512}
172 disabled_fns: map[string]bool{}
173 export_fn_names: map[string]string{}
174 }
175}
176
177// add updates add state for FlatAst.
178pub fn (mut a FlatAst) add(kind NodeKind) NodeId {
179 id := NodeId(a.nodes.len)
180 a.nodes << Node{
181 kind: kind
182 kind_id: int(kind)
183 }
184 return id
185}
186
187// add_id updates add id state for FlatAst.
188pub fn (mut a FlatAst) add_id(kind_id int) NodeId {
189 id := NodeId(a.nodes.len)
190 a.nodes << Node{
191 kind: node_kind_from_id(kind_id)
192 kind_id: kind_id
193 }
194 return id
195}
196
197// node_kind_from_id converts node kind from id data for flat.
198@[inline]
199pub fn node_kind_from_id(id int) NodeKind {
200 return unsafe { NodeKind(id) }
201}
202
203// add_val updates add val state for FlatAst.
204pub fn (mut a FlatAst) add_val(kind NodeKind, value string) NodeId {
205 id := NodeId(a.nodes.len)
206 a.nodes << Node{
207 kind: kind
208 kind_id: int(kind)
209 value: value
210 }
211 return id
212}
213
214// add_val_id updates add val id state for FlatAst.
215pub fn (mut a FlatAst) add_val_id(kind_id int, value string) NodeId {
216 id := NodeId(a.nodes.len)
217 a.nodes << Node{
218 kind: node_kind_from_id(kind_id)
219 kind_id: kind_id
220 value: value
221 }
222 return id
223}
224
225// with_shifted_children returns a copy of the node whose children_start is moved
226// by `shift`. children_start lives in the immutable section of Node, so callers
227// that relocate a node's children block (e.g. the parallel-transform merge) build
228// a fresh node instead of mutating in place.
229pub fn (n Node) with_shifted_children(shift i32) Node {
230 return Node{
231 value: n.value
232 typ: n.typ
233 generic_params: n.generic_params
234 kind_id: n.kind_id
235 pos: n.pos
236 children_start: n.children_start + shift
237 children_count: n.children_count
238 kind: n.kind
239 op: n.op
240 }
241}
242
243// add_node updates add node state for FlatAst.
244pub fn (mut a FlatAst) add_node(node Node) NodeId {
245 id := NodeId(a.nodes.len)
246 mut n := node
247 if n.kind_id == 0 && int(n.kind) != 0 {
248 n.kind_id = int(n.kind)
249 }
250 a.nodes << n
251 return id
252}
253
254// child_count converts a dynamic child count to Node's compact storage type.
255pub fn child_count(count int) i16 {
256 if count > 32767 {
257 panic('flat node has too many children')
258 }
259 return i16(count)
260}
261
262// begin_children supports begin children handling for FlatAst.
263pub fn (mut a FlatAst) begin_children() int {
264 return a.children.len
265}
266
267// add_child updates add child state for FlatAst.
268pub fn (mut a FlatAst) add_child(id NodeId) {
269 a.children << id
270}
271
272// child supports child handling for FlatAst.
273pub fn (a &FlatAst) child(node &Node, index int) NodeId {
274 child_index := node.children_start + index
275 if index < 0 || index >= node.children_count || child_index < 0 || child_index >= a.children.len {
276 return empty_node
277 }
278 return a.children[child_index]
279}
280
281// child_node supports child node handling for FlatAst.
282pub fn (a &FlatAst) child_node(node &Node, index int) &Node {
283 id := a.child(node, index)
284 if int(id) < 0 || int(id) >= a.nodes.len {
285 return &empty_node_value
286 }
287 return &a.nodes[int(id)]
288}
289
290// node supports node handling for FlatAst.
291pub fn (a &FlatAst) node(id NodeId) &Node {
292 if int(id) < 0 || int(id) >= a.nodes.len {
293 return &empty_node_value
294 }
295 return &a.nodes[int(id)]
296}
297
298// children_of supports children of handling for FlatAst.
299pub fn (a &FlatAst) children_of(node &Node) []NodeId {
300 if node.children_count == 0 {
301 return []
302 }
303 if node.children_start < 0 || node.children_start >= a.children.len {
304 return []
305 }
306 if node.children_start + node.children_count > a.children.len {
307 return a.children[node.children_start..]
308 }
309 return a.children[node.children_start..node.children_start + node.children_count]
310}
311
312// print_tree updates print tree state for FlatAst.
313pub fn (a &FlatAst) print_tree(id NodeId, indent int) {
314 node := a.nodes[int(id)]
315 mut prefix := ''
316 for _ in 0 .. indent {
317 prefix += ' '
318 }
319 mut info := '${node.kind}'
320 if node.value.len > 0 {
321 info += ' "${node.value}"'
322 }
323 if node.op != .none {
324 info += ' op=${node.op}'
325 }
326 if node.typ.len > 0 {
327 info += ' typ=${node.typ}'
328 }
329 println('${prefix}${info}')
330 for i in 0 .. node.children_count {
331 child_id := a.children[node.children_start + i]
332 if int(child_id) >= 0 {
333 a.print_tree(child_id, indent + 1)
334 }
335 }
336}
337