v / vlib / v2 / ast / flat_reader.v
1199 lines · 1163 sloc · 29.41 KB · 34038bec7b93f4e3ddbbdcbe88ea21f4693eee43
Raw
1// Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module ast
5
6import v2.token
7
8// to_files materializes a FlatAst back into legacy []File. This is the
9// inverse of flatten_files() and is used for round-trip verification.
10// Reading happens lazily (one node at a time) so callers can also walk a
11// flat AST without ever rehydrating the legacy form.
12pub fn (flat &FlatAst) to_files() []File {
13 r := FlatReader{
14 flat: unsafe { flat }
15 }
16 mut files := []File{cap: flat.files.len}
17 for ff in flat.files {
18 files << r.read_file(ff)
19 }
20 return files
21}
22
23// to_files_range rehydrates the FlatFiles in [start, end) without touching
24// the rest of the FlatAst. Used by the streaming builder, where each
25// parse_batch appends to a shared FlatBuilder and only needs to return the
26// freshly added files to the caller.
27pub fn (flat &FlatAst) to_files_range(start int, end int) []File {
28 mut lo := start
29 mut hi := end
30 if lo < 0 {
31 lo = 0
32 }
33 if hi > flat.files.len {
34 hi = flat.files.len
35 }
36 if hi <= lo {
37 return []File{}
38 }
39 r := FlatReader{
40 flat: unsafe { flat }
41 }
42 mut files := []File{cap: hi - lo}
43 for i in lo .. hi {
44 files << r.read_file(flat.files[i])
45 }
46 return files
47}
48
49// FlatReader is a thin cursor over a FlatAst that reconstructs legacy nodes.
50struct FlatReader {
51 flat &FlatAst
52}
53
54@[inline]
55fn (r &FlatReader) node(id FlatNodeId) FlatNode {
56 return r.flat.nodes[id]
57}
58
59@[inline]
60fn (r &FlatReader) edge(n FlatNode, i int) FlatNodeId {
61 return r.flat.edges[n.first_edge + i].child_id
62}
63
64@[inline]
65fn (r &FlatReader) get_str(idx int) string {
66 if idx < 0 || idx >= r.flat.strings.len {
67 return ''
68 }
69 return r.flat.strings[idx]
70}
71
72// list_children returns the child ids of an aux_list node.
73fn (r &FlatReader) list_children(id FlatNodeId) []FlatNodeId {
74 if id < 0 {
75 return []FlatNodeId{}
76 }
77 n := r.node(id)
78 mut out := []FlatNodeId{cap: n.edge_count}
79 for i in 0 .. n.edge_count {
80 out << r.edge(n, i)
81 }
82 return out
83}
84
85fn (r &FlatReader) read_file(ff FlatFile) File {
86 n := r.node(ff.file_id)
87 attrs_id := r.edge(n, 0)
88 imports_id := r.edge(n, 1)
89 stmts_id := r.edge(n, 2)
90 mut attrs := []Attribute{}
91 attr_children := r.list_children(attrs_id)
92 for cid in attr_children {
93 attrs << r.read_attribute(cid)
94 }
95 mut imports := []ImportStmt{}
96 import_children := r.list_children(imports_id)
97 for cid in import_children {
98 c := Cursor{
99 flat: r.flat
100 id: cid
101 }
102 if c.kind() == .stmt_import {
103 imports << c.import_stmt()
104 }
105 }
106 mut stmts := []Stmt{}
107 stmt_children := r.list_children(stmts_id)
108 for cid in stmt_children {
109 stmts << r.read_stmt(cid)
110 }
111 return File{
112 name: r.get_str(ff.name_idx)
113 mod: r.get_str(ff.mod_idx)
114 selector_names: ff.selector_names
115 attributes: attrs
116 imports: imports
117 stmts: stmts
118 }
119}
120
121// decode_stmt rehydrates a single legacy ast.Stmt from a FlatNodeId. Useful
122// for cursor-driven consumers that walk the flat graph via Cursor and only
123// need to materialize a typed Stmt for the specific decls they hand to
124// helpers still keyed on legacy ADTs. Returns empty_stmt for invalid ids.
125pub fn (flat &FlatAst) decode_stmt(id FlatNodeId) Stmt {
126 r := FlatReader{
127 flat: unsafe { flat }
128 }
129 return r.read_stmt(id)
130}
131
132// decode_expr is the Expr analogue of decode_stmt.
133pub fn (flat &FlatAst) decode_expr(id FlatNodeId) Expr {
134 r := FlatReader{
135 flat: unsafe { flat }
136 }
137 return r.read_expr(id)
138}
139
140// decode_fn_decl_signature rehydrates a FnDecl with `stmts = []` — the body
141// is left empty. Callers that walk the body via Cursor (e.g. markused) can
142// use this to avoid the per-fn body decode, which dominates collect_defs
143// time in flat mode. Returns an empty FnDecl for ids that don't point at a
144// stmt_fn_decl node.
145pub fn (flat &FlatAst) decode_fn_decl_signature(id FlatNodeId) FnDecl {
146 if id < 0 || id >= flat.nodes.len {
147 return FnDecl{}
148 }
149 n := flat.nodes[id]
150 if n.kind != .stmt_fn_decl {
151 return FnDecl{}
152 }
153 r := FlatReader{
154 flat: unsafe { flat }
155 }
156 recv_id := r.edge(n, 0)
157 typ_id := r.edge(n, 1)
158 attrs_id := r.edge(n, 2)
159 fn_typ := r.read_fn_type(typ_id)
160 return FnDecl{
161 attributes: r.read_attr_list(attrs_id)
162 is_public: (n.flags & flag_is_public) != 0
163 is_method: (n.flags & flag_is_method) != 0
164 is_static: (n.flags & flag_is_static) != 0
165 receiver: r.read_parameter(recv_id)
166 language: unsafe { Language(int(n.aux)) }
167 name: r.get_str(n.name_id)
168 typ: fn_typ
169 pos: n.pos
170 }
171}
172
173// file_mod returns the module name for a FlatFile via the interned strings.
174@[inline]
175pub fn (flat &FlatAst) file_mod(ff FlatFile) string {
176 if ff.mod_idx < 0 || ff.mod_idx >= flat.strings.len {
177 return ''
178 }
179 return flat.strings[ff.mod_idx]
180}
181
182// file_name returns the source filename for a FlatFile.
183@[inline]
184pub fn (flat &FlatAst) file_name(ff FlatFile) string {
185 if ff.name_idx < 0 || ff.name_idx >= flat.strings.len {
186 return ''
187 }
188 return flat.strings[ff.name_idx]
189}
190
191fn (r &FlatReader) read_attribute(id FlatNodeId) Attribute {
192 n := r.node(id)
193 return Attribute{
194 name: r.get_str(n.name_id)
195 value: r.read_expr(r.edge(n, 0))
196 comptime_cond: r.read_expr(r.edge(n, 1))
197 }
198}
199
200fn (r &FlatReader) read_field_init(id FlatNodeId) FieldInit {
201 n := r.node(id)
202 return FieldInit{
203 name: r.get_str(n.name_id)
204 value: r.read_expr(r.edge(n, 0))
205 }
206}
207
208fn (r &FlatReader) read_field_decl(id FlatNodeId) FieldDecl {
209 n := r.node(id)
210 attrs_id := r.edge(n, 2)
211 mut attrs := []Attribute{}
212 attr_children := r.list_children(attrs_id)
213 for cid in attr_children {
214 attrs << r.read_attribute(cid)
215 }
216 return FieldDecl{
217 name: r.get_str(n.name_id)
218 typ: r.read_expr(r.edge(n, 0))
219 value: r.read_expr(r.edge(n, 1))
220 attributes: attrs
221 is_public: (n.flags & flag_is_public) != 0
222 is_mut: (n.flags & flag_is_mut) != 0
223 is_module_mut: (n.flags & flag_field_is_module_mut) != 0
224 is_interface_method: (n.flags & flag_field_is_interface_method) != 0
225 }
226}
227
228fn (r &FlatReader) read_parameter(id FlatNodeId) Parameter {
229 n := r.node(id)
230 return Parameter{
231 name: r.get_str(n.name_id)
232 typ: r.read_expr(r.edge(n, 0))
233 is_mut: (n.flags & flag_is_mut) != 0
234 pos: n.pos
235 }
236}
237
238fn (r &FlatReader) read_match_branch(id FlatNodeId) MatchBranch {
239 n := r.node(id)
240 cond_id := r.edge(n, 0)
241 stmts_id := r.edge(n, 1)
242 mut cond := []Expr{}
243 cond_children := r.list_children(cond_id)
244 for cid in cond_children {
245 cond << r.read_expr(cid)
246 }
247 mut stmts := []Stmt{}
248 stmt_children := r.list_children(stmts_id)
249 for cid in stmt_children {
250 stmts << r.read_stmt(cid)
251 }
252 return MatchBranch{
253 cond: cond
254 stmts: stmts
255 pos: n.pos
256 }
257}
258
259fn (r &FlatReader) read_string_inter(id FlatNodeId) StringInter {
260 n := r.node(id)
261 mut width := 0
262 mut precision := 0
263 if n.edge_count >= 4 {
264 width = r.read_int(r.edge(n, 2))
265 precision = r.read_int(r.edge(n, 3))
266 } else {
267 packed := n.extra
268 width = (packed >> 16) & 0xFFFF
269 // sign-extend the low 16 bits to recover negative precision values
270 precision = packed & 0xFFFF
271 if precision & 0x8000 != 0 {
272 precision |= ~0xFFFF
273 }
274 // sign-extend width as well
275 if width & 0x8000 != 0 {
276 width |= ~0xFFFF
277 }
278 }
279 return StringInter{
280 format: unsafe { StringInterFormat(int(n.aux)) }
281 width: width
282 precision: precision
283 expr: r.read_expr(r.edge(n, 0))
284 format_expr: r.read_expr(r.edge(n, 1))
285 resolved_fmt: r.get_str(n.name_id)
286 }
287}
288
289fn (r &FlatReader) read_int(id FlatNodeId) int {
290 return r.node(id).extra
291}
292
293fn (r &FlatReader) read_expr_list(id FlatNodeId) []Expr {
294 mut out := []Expr{}
295 children := r.list_children(id)
296 for cid in children {
297 out << r.read_expr(cid)
298 }
299 return out
300}
301
302fn (r &FlatReader) read_stmt_list(id FlatNodeId) []Stmt {
303 mut out := []Stmt{}
304 children := r.list_children(id)
305 for cid in children {
306 out << r.read_stmt(cid)
307 }
308 return out
309}
310
311fn (r &FlatReader) read_attr_list(id FlatNodeId) []Attribute {
312 mut out := []Attribute{}
313 children := r.list_children(id)
314 for cid in children {
315 out << r.read_attribute(cid)
316 }
317 return out
318}
319
320fn (r &FlatReader) read_field_decl_list(id FlatNodeId) []FieldDecl {
321 mut out := []FieldDecl{}
322 children := r.list_children(id)
323 for cid in children {
324 out << r.read_field_decl(cid)
325 }
326 return out
327}
328
329fn (r &FlatReader) read_field_init_list(id FlatNodeId) []FieldInit {
330 mut out := []FieldInit{}
331 children := r.list_children(id)
332 for cid in children {
333 out << r.read_field_init(cid)
334 }
335 return out
336}
337
338fn (r &FlatReader) read_parameter_list(id FlatNodeId) []Parameter {
339 mut out := []Parameter{}
340 children := r.list_children(id)
341 for cid in children {
342 out << r.read_parameter(cid)
343 }
344 return out
345}
346
347// read_fn_type (s252) decodes a `.typ_fn` node straight into a FnType, without
348// the read_type→`Type(FnType{...})`→`is FnType` round-trip. Boxing a large
349// struct into the Type sum type and then unboxing it via smartcast corrupts the
350// FnType's slice headers (generic_params/params) on the arm64 self-host (the
351// documented chained-access/smartcast bug). This path is only ever exercised by
352// the flat decode, so the default self-host never hit it. Edge layout matches
353// the encoder's FnType arm and read_type's `.typ_fn`: 0=generics, 1=params,
354// 2=return_type.
355fn (r &FlatReader) read_fn_type(id FlatNodeId) FnType {
356 if id < 0 {
357 return FnType{}
358 }
359 n := r.node(id)
360 if n.kind != .typ_fn {
361 return FnType{}
362 }
363 return FnType{
364 generic_params: r.read_expr_list(r.edge(n, 0))
365 params: r.read_parameter_list(r.edge(n, 1))
366 return_type: r.read_expr(r.edge(n, 2))
367 }
368}
369
370// read_ident (s254) decodes an expr_ident node straight into an Ident, avoiding
371// the read_expr→Expr→`is Ident` smartcast-unbox. Copying a struct out of the Expr
372// sum type via smartcast corrupts its fields (here the `name` string header) on
373// the arm64 self-host (same chained-access/smartcast bug as the FnType unbox in
374// s252). Returns an empty Ident for ids that don't point at an expr_ident.
375fn (r &FlatReader) read_ident(id FlatNodeId) Ident {
376 if id < 0 || id >= r.flat.nodes.len {
377 return Ident{}
378 }
379 n := r.node(id)
380 if n.kind != .expr_ident {
381 return Ident{}
382 }
383 return Ident{
384 pos: n.pos
385 name: r.get_str(n.name_id)
386 }
387}
388
389// read_assign_stmt (s254) decodes a stmt_assign node straight into an AssignStmt,
390// avoiding the read_stmt→Stmt→`is AssignStmt` unbox (which corrupts the lhs/rhs
391// slice headers on arm64). Mirrors the `.stmt_assign` arm of read_stmt. Returns
392// an empty AssignStmt for ids that don't point at a stmt_assign.
393fn (r &FlatReader) read_assign_stmt(id FlatNodeId) AssignStmt {
394 if id < 0 || id >= r.flat.nodes.len {
395 return AssignStmt{}
396 }
397 n := r.node(id)
398 if n.kind != .stmt_assign {
399 return AssignStmt{}
400 }
401 lhs_len := n.extra
402 mut lhs := []Expr{cap: lhs_len}
403 for i in 0 .. lhs_len {
404 lhs << r.read_expr(r.edge(n, i))
405 }
406 mut rhs := []Expr{cap: n.edge_count - lhs_len}
407 for i in lhs_len .. n.edge_count {
408 rhs << r.read_expr(r.edge(n, i))
409 }
410 return AssignStmt{
411 op: unsafe { token.Token(int(n.aux)) }
412 lhs: lhs
413 rhs: rhs
414 pos: n.pos
415 }
416}
417
418fn (r &FlatReader) read_string_list(id FlatNodeId) []string {
419 if id < 0 {
420 return []string{}
421 }
422 n := r.node(id)
423 mut out := []string{cap: n.edge_count}
424 for i in 0 .. n.edge_count {
425 child := r.node(r.edge(n, i))
426 out << r.get_str(child.name_id)
427 }
428 return out
429}
430
431fn (r &FlatReader) read_string_inter_list(id FlatNodeId) []StringInter {
432 mut out := []StringInter{}
433 children := r.list_children(id)
434 for cid in children {
435 out << r.read_string_inter(cid)
436 }
437 return out
438}
439
440fn (r &FlatReader) read_stmt(id FlatNodeId) Stmt {
441 if id < 0 {
442 return empty_stmt
443 }
444 n := r.node(id)
445 match n.kind {
446 .stmt_asm {
447 return Stmt(AsmStmt{
448 arch: r.get_str(n.name_id)
449 })
450 }
451 .stmt_assert {
452 return Stmt(AssertStmt{
453 expr: r.read_expr(r.edge(n, 0))
454 extra: r.read_expr(r.edge(n, 1))
455 })
456 }
457 .stmt_assign {
458 lhs_len := n.extra
459 mut lhs := []Expr{cap: lhs_len}
460 for i in 0 .. lhs_len {
461 lhs << r.read_expr(r.edge(n, i))
462 }
463 mut rhs := []Expr{cap: n.edge_count - lhs_len}
464 for i in lhs_len .. n.edge_count {
465 rhs << r.read_expr(r.edge(n, i))
466 }
467 return Stmt(AssignStmt{
468 op: unsafe { token.Token(int(n.aux)) }
469 lhs: lhs
470 rhs: rhs
471 pos: n.pos
472 })
473 }
474 .stmt_block {
475 mut stmts := []Stmt{cap: n.edge_count}
476 for i in 0 .. n.edge_count {
477 stmts << r.read_stmt(r.edge(n, i))
478 }
479 return Stmt(BlockStmt{
480 stmts: stmts
481 })
482 }
483 .stmt_comptime {
484 return Stmt(ComptimeStmt{
485 stmt: r.read_stmt(r.edge(n, 0))
486 })
487 }
488 .stmt_const_decl {
489 fields_id := r.edge(n, 0)
490 return Stmt(ConstDecl{
491 is_public: (n.flags & flag_is_public) != 0
492 fields: r.read_field_init_list(fields_id)
493 })
494 }
495 .stmt_defer {
496 mode := if (n.flags & flag_defer_func) != 0 {
497 DeferMode.function
498 } else {
499 DeferMode.scoped
500 }
501 mut stmts := []Stmt{cap: n.edge_count}
502 for i in 0 .. n.edge_count {
503 stmts << r.read_stmt(r.edge(n, i))
504 }
505 return Stmt(DeferStmt{
506 mode: mode
507 stmts: stmts
508 })
509 }
510 .stmt_directive {
511 mut ct_cond := ''
512 if n.edge_count > 0 {
513 cc_node := r.node(r.edge(n, 0))
514 ct_cond = r.get_str(cc_node.name_id)
515 }
516 return Stmt(Directive{
517 name: r.get_str(n.name_id)
518 value: r.get_str(n.extra)
519 ct_cond: ct_cond
520 })
521 }
522 .stmt_empty {
523 return Stmt(EmptyStmt(u8(n.extra)))
524 }
525 .stmt_enum_decl {
526 as_type := r.read_expr(r.edge(n, 0))
527 attrs_id := r.edge(n, 1)
528 fields_id := r.edge(n, 2)
529 return Stmt(EnumDecl{
530 is_public: (n.flags & flag_is_public) != 0
531 name: r.get_str(n.name_id)
532 as_type: as_type
533 attributes: r.read_attr_list(attrs_id)
534 fields: r.read_field_decl_list(fields_id)
535 })
536 }
537 .stmt_expr {
538 return Stmt(ExprStmt{
539 expr: r.read_expr(r.edge(n, 0))
540 })
541 }
542 .stmt_flow_control {
543 return Stmt(FlowControlStmt{
544 op: unsafe { token.Token(int(n.aux)) }
545 label: r.get_str(n.name_id)
546 })
547 }
548 .stmt_fn_decl {
549 recv_id := r.edge(n, 0)
550 typ_id := r.edge(n, 1)
551 attrs_id := r.edge(n, 2)
552 stmts_id := r.edge(n, 3)
553 fn_typ := r.read_fn_type(typ_id)
554 return Stmt(FnDecl{
555 attributes: r.read_attr_list(attrs_id)
556 is_public: (n.flags & flag_is_public) != 0
557 is_method: (n.flags & flag_is_method) != 0
558 is_static: (n.flags & flag_is_static) != 0
559 receiver: r.read_parameter(recv_id)
560 language: unsafe { Language(int(n.aux)) }
561 name: r.get_str(n.name_id)
562 typ: fn_typ
563 stmts: r.read_stmt_list(stmts_id)
564 pos: n.pos
565 })
566 }
567 .stmt_for_in {
568 return Stmt(ForInStmt{
569 key: r.read_expr(r.edge(n, 0))
570 value: r.read_expr(r.edge(n, 1))
571 expr: r.read_expr(r.edge(n, 2))
572 })
573 }
574 .stmt_for {
575 init := r.read_stmt(r.edge(n, 0))
576 cond := r.read_expr(r.edge(n, 1))
577 post := r.read_stmt(r.edge(n, 2))
578 mut stmts := []Stmt{cap: n.edge_count - 3}
579 for i in 3 .. n.edge_count {
580 stmts << r.read_stmt(r.edge(n, i))
581 }
582 return Stmt(ForStmt{
583 init: init
584 cond: cond
585 post: post
586 stmts: stmts
587 })
588 }
589 .stmt_global_decl {
590 attrs_id := r.edge(n, 0)
591 fields_id := r.edge(n, 1)
592 return Stmt(GlobalDecl{
593 attributes: r.read_attr_list(attrs_id)
594 fields: r.read_field_decl_list(fields_id)
595 is_public: (n.flags & flag_is_public) != 0
596 })
597 }
598 .stmt_import {
599 mut symbols := []Expr{cap: n.edge_count}
600 for i in 0 .. n.edge_count {
601 symbols << r.read_expr(r.edge(n, i))
602 }
603 return Stmt(ImportStmt{
604 name: r.get_str(n.name_id)
605 alias: r.get_str(n.extra)
606 is_aliased: (n.flags & flag_is_aliased) != 0
607 symbols: symbols
608 })
609 }
610 .stmt_interface_decl {
611 attrs_id := r.edge(n, 0)
612 generic_params_id := r.edge(n, 1)
613 embedded_id := r.edge(n, 2)
614 fields_id := r.edge(n, 3)
615 return Stmt(InterfaceDecl{
616 is_public: (n.flags & flag_is_public) != 0
617 attributes: r.read_attr_list(attrs_id)
618 name: r.get_str(n.name_id)
619 generic_params: r.read_expr_list(generic_params_id)
620 embedded: r.read_expr_list(embedded_id)
621 fields: r.read_field_decl_list(fields_id)
622 })
623 }
624 .stmt_label {
625 return Stmt(LabelStmt{
626 name: r.get_str(n.name_id)
627 stmt: r.read_stmt(r.edge(n, 0))
628 })
629 }
630 .stmt_module {
631 return Stmt(ModuleStmt{
632 name: r.get_str(n.name_id)
633 })
634 }
635 .stmt_return {
636 mut exprs := []Expr{cap: n.edge_count}
637 for i in 0 .. n.edge_count {
638 exprs << r.read_expr(r.edge(n, i))
639 }
640 return Stmt(ReturnStmt{
641 exprs: exprs
642 })
643 }
644 .stmt_struct_decl {
645 attrs_id := r.edge(n, 0)
646 implements_id := r.edge(n, 1)
647 embedded_id := r.edge(n, 2)
648 generic_params_id := r.edge(n, 3)
649 fields_id := r.edge(n, 4)
650 return Stmt(StructDecl{
651 attributes: r.read_attr_list(attrs_id)
652 is_public: (n.flags & flag_is_public) != 0
653 is_union: (n.flags & flag_is_union) != 0
654 implements: r.read_expr_list(implements_id)
655 embedded: r.read_expr_list(embedded_id)
656 language: unsafe { Language(int(n.aux)) }
657 name: r.get_str(n.name_id)
658 generic_params: r.read_expr_list(generic_params_id)
659 fields: r.read_field_decl_list(fields_id)
660 pos: n.pos
661 })
662 }
663 .stmt_type_decl {
664 base_type := r.read_expr(r.edge(n, 0))
665 generic_params_id := r.edge(n, 2)
666 variants_id := r.edge(n, 3)
667 return Stmt(TypeDecl{
668 is_public: (n.flags & flag_is_public) != 0
669 language: unsafe { Language(int(n.aux)) }
670 name: r.get_str(n.name_id)
671 generic_params: r.read_expr_list(generic_params_id)
672 base_type: base_type
673 variants: r.read_expr_list(variants_id)
674 })
675 }
676 .stmt_attributes {
677 list_id := r.edge(n, 0)
678 return Stmt(r.read_attr_list(list_id))
679 }
680 else {
681 return empty_stmt
682 }
683 }
684}
685
686fn (r &FlatReader) read_expr(id FlatNodeId) Expr {
687 if id < 0 {
688 return empty_expr
689 }
690 n := r.node(id)
691 // Types and aux nodes can appear where an Expr is expected.
692 match n.kind {
693 .typ_anon_struct, .typ_array_fixed, .typ_array, .typ_channel, .typ_fn, .typ_generic,
694 .typ_map, .typ_nil, .typ_none, .typ_option, .typ_pointer, .typ_result, .typ_thread,
695 .typ_tuple {
696 return Expr(r.read_type(id))
697 }
698 .aux_field_init {
699 return Expr(r.read_field_init(id))
700 }
701 else {}
702 }
703
704 match n.kind {
705 .expr_array_init {
706 typ := r.read_expr(r.edge(n, 0))
707 init := r.read_expr(r.edge(n, 1))
708 cap := r.read_expr(r.edge(n, 2))
709 len := r.read_expr(r.edge(n, 3))
710 update_expr := r.read_expr(r.edge(n, 4))
711 mut exprs := []Expr{cap: n.edge_count - 5}
712 for i in 5 .. n.edge_count {
713 exprs << r.read_expr(r.edge(n, i))
714 }
715 return Expr(ArrayInitExpr{
716 typ: typ
717 exprs: exprs
718 init: init
719 cap: cap
720 len: len
721 update_expr: update_expr
722 pos: n.pos
723 })
724 }
725 .expr_as_cast {
726 return Expr(AsCastExpr{
727 expr: r.read_expr(r.edge(n, 0))
728 typ: r.read_expr(r.edge(n, 1))
729 pos: n.pos
730 })
731 }
732 .expr_assoc {
733 typ := r.read_expr(r.edge(n, 0))
734 expr := r.read_expr(r.edge(n, 1))
735 mut fields := []FieldInit{cap: n.edge_count - 2}
736 for i in 2 .. n.edge_count {
737 fields << r.read_field_init(r.edge(n, i))
738 }
739 return Expr(AssocExpr{
740 typ: typ
741 expr: expr
742 fields: fields
743 pos: n.pos
744 })
745 }
746 .expr_basic_literal {
747 return Expr(BasicLiteral{
748 kind: unsafe { token.Token(int(n.aux)) }
749 value: r.get_str(n.name_id)
750 pos: n.pos
751 })
752 }
753 .expr_call {
754 lhs := r.read_expr(r.edge(n, 0))
755 mut args := []Expr{cap: n.edge_count - 1}
756 for i in 1 .. n.edge_count {
757 args << r.read_expr(r.edge(n, i))
758 }
759 return Expr(CallExpr{
760 lhs: lhs
761 args: args
762 pos: n.pos
763 })
764 }
765 .expr_call_or_cast {
766 return Expr(CallOrCastExpr{
767 lhs: r.read_expr(r.edge(n, 0))
768 expr: r.read_expr(r.edge(n, 1))
769 pos: n.pos
770 })
771 }
772 .expr_cast {
773 return Expr(CastExpr{
774 typ: r.read_expr(r.edge(n, 0))
775 expr: r.read_expr(r.edge(n, 1))
776 pos: n.pos
777 })
778 }
779 .expr_comptime {
780 return Expr(ComptimeExpr{
781 expr: r.read_expr(r.edge(n, 0))
782 pos: n.pos
783 })
784 }
785 .expr_empty {
786 return Expr(EmptyExpr(u8(n.extra)))
787 }
788 .expr_fn_literal {
789 fn_typ_id := r.edge(n, 0)
790 fn_typ := r.read_fn_type(fn_typ_id)
791 cap_len := n.extra
792 mut captured := []Expr{cap: cap_len}
793 for i in 0 .. cap_len {
794 captured << r.read_expr(r.edge(n, 1 + i))
795 }
796 mut stmts := []Stmt{cap: n.edge_count - 1 - cap_len}
797 for i in (1 + cap_len) .. n.edge_count {
798 stmts << r.read_stmt(r.edge(n, i))
799 }
800 return Expr(FnLiteral{
801 typ: fn_typ
802 captured_vars: captured
803 stmts: stmts
804 pos: n.pos
805 })
806 }
807 .expr_generic_arg_or_index {
808 return Expr(GenericArgOrIndexExpr{
809 lhs: r.read_expr(r.edge(n, 0))
810 expr: r.read_expr(r.edge(n, 1))
811 pos: n.pos
812 })
813 }
814 .expr_generic_args {
815 lhs := r.read_expr(r.edge(n, 0))
816 mut args := []Expr{cap: n.edge_count - 1}
817 for i in 1 .. n.edge_count {
818 args << r.read_expr(r.edge(n, i))
819 }
820 return Expr(GenericArgs{
821 lhs: lhs
822 args: args
823 pos: n.pos
824 })
825 }
826 .expr_ident {
827 return Expr(Ident{
828 pos: n.pos
829 name: r.get_str(n.name_id)
830 })
831 }
832 .expr_if {
833 cond := r.read_expr(r.edge(n, 0))
834 else_expr := r.read_expr(r.edge(n, 1))
835 mut stmts := []Stmt{cap: n.edge_count - 2}
836 for i in 2 .. n.edge_count {
837 stmts << r.read_stmt(r.edge(n, i))
838 }
839 return Expr(IfExpr{
840 cond: cond
841 else_expr: else_expr
842 stmts: stmts
843 pos: n.pos
844 })
845 }
846 .expr_if_guard {
847 // s254: read the assign straight into an AssignStmt; the old
848 // `read_stmt → if child is AssignStmt { child }` unbox corrupted its
849 // lhs/rhs slice headers on arm64.
850 return Expr(IfGuardExpr{
851 stmt: r.read_assign_stmt(r.edge(n, 0))
852 pos: n.pos
853 })
854 }
855 .expr_index {
856 return Expr(IndexExpr{
857 lhs: r.read_expr(r.edge(n, 0))
858 expr: r.read_expr(r.edge(n, 1))
859 is_gated: (n.flags & flag_is_gated) != 0
860 pos: n.pos
861 })
862 }
863 .expr_infix {
864 return Expr(InfixExpr{
865 op: unsafe { token.Token(int(n.aux)) }
866 lhs: r.read_expr(r.edge(n, 0))
867 rhs: r.read_expr(r.edge(n, 1))
868 pos: n.pos
869 })
870 }
871 .expr_init {
872 typ := r.read_expr(r.edge(n, 0))
873 mut fields := []FieldInit{cap: n.edge_count - 1}
874 for i in 1 .. n.edge_count {
875 fields << r.read_field_init(r.edge(n, i))
876 }
877 return Expr(InitExpr{
878 typ: typ
879 fields: fields
880 pos: n.pos
881 })
882 }
883 .expr_keyword {
884 return Expr(Keyword{
885 tok: unsafe { token.Token(int(n.aux)) }
886 })
887 }
888 .expr_keyword_operator {
889 mut exprs := []Expr{cap: n.edge_count}
890 for i in 0 .. n.edge_count {
891 exprs << r.read_expr(r.edge(n, i))
892 }
893 return Expr(KeywordOperator{
894 op: unsafe { token.Token(int(n.aux)) }
895 exprs: exprs
896 pos: n.pos
897 })
898 }
899 .expr_lambda {
900 expr := r.read_expr(r.edge(n, 0))
901 mut args := []Ident{cap: n.edge_count - 1}
902 for i in 1 .. n.edge_count {
903 // s254: read each arg straight into an Ident (the old
904 // `read_expr → if e is Ident { args << e }` unbox corrupted the
905 // Ident's `name` on arm64).
906 arg_id := r.edge(n, i)
907 if arg_id >= 0 && arg_id < r.flat.nodes.len && r.node(arg_id).kind == .expr_ident {
908 args << r.read_ident(arg_id)
909 }
910 }
911 return Expr(LambdaExpr{
912 args: args
913 expr: expr
914 pos: n.pos
915 })
916 }
917 .expr_lifetime {
918 return Expr(LifetimeExpr{
919 name: r.get_str(n.name_id)
920 pos: n.pos
921 })
922 }
923 .expr_lock {
924 packed := u32(n.extra)
925 lock_len := int(packed & 0xFFFF)
926 rlock_len := int((packed >> 16) & 0xFFFF)
927 mut lock_exprs := []Expr{cap: lock_len}
928 for i in 0 .. lock_len {
929 lock_exprs << r.read_expr(r.edge(n, i))
930 }
931 mut rlock_exprs := []Expr{cap: rlock_len}
932 for i in lock_len .. (lock_len + rlock_len) {
933 rlock_exprs << r.read_expr(r.edge(n, i))
934 }
935 mut stmts := []Stmt{cap: n.edge_count - lock_len - rlock_len}
936 for i in (lock_len + rlock_len) .. n.edge_count {
937 stmts << r.read_stmt(r.edge(n, i))
938 }
939 return Expr(LockExpr{
940 lock_exprs: lock_exprs
941 rlock_exprs: rlock_exprs
942 stmts: stmts
943 pos: n.pos
944 })
945 }
946 .expr_map_init {
947 typ := r.read_expr(r.edge(n, 0))
948 keys_len := n.extra
949 mut keys := []Expr{cap: keys_len}
950 for i in 0 .. keys_len {
951 keys << r.read_expr(r.edge(n, 1 + i))
952 }
953 mut vals := []Expr{cap: n.edge_count - 1 - keys_len}
954 for i in (1 + keys_len) .. n.edge_count {
955 vals << r.read_expr(r.edge(n, i))
956 }
957 return Expr(MapInitExpr{
958 typ: typ
959 keys: keys
960 vals: vals
961 pos: n.pos
962 })
963 }
964 .expr_match {
965 expr := r.read_expr(r.edge(n, 0))
966 mut branches := []MatchBranch{cap: n.edge_count - 1}
967 for i in 1 .. n.edge_count {
968 branches << r.read_match_branch(r.edge(n, i))
969 }
970 return Expr(MatchExpr{
971 expr: expr
972 branches: branches
973 pos: n.pos
974 })
975 }
976 .expr_modifier {
977 return Expr(ModifierExpr{
978 kind: unsafe { token.Token(int(n.aux)) }
979 expr: r.read_expr(r.edge(n, 0))
980 pos: n.pos
981 })
982 }
983 .expr_or {
984 expr := r.read_expr(r.edge(n, 0))
985 mut stmts := []Stmt{cap: n.edge_count - 1}
986 for i in 1 .. n.edge_count {
987 stmts << r.read_stmt(r.edge(n, i))
988 }
989 return Expr(OrExpr{
990 expr: expr
991 stmts: stmts
992 pos: n.pos
993 })
994 }
995 .expr_paren {
996 return Expr(ParenExpr{
997 expr: r.read_expr(r.edge(n, 0))
998 pos: n.pos
999 })
1000 }
1001 .expr_postfix {
1002 return Expr(PostfixExpr{
1003 op: unsafe { token.Token(int(n.aux)) }
1004 expr: r.read_expr(r.edge(n, 0))
1005 pos: n.pos
1006 })
1007 }
1008 .expr_prefix {
1009 return Expr(PrefixExpr{
1010 op: unsafe { token.Token(int(n.aux)) }
1011 expr: r.read_expr(r.edge(n, 0))
1012 pos: n.pos
1013 })
1014 }
1015 .expr_range {
1016 return Expr(RangeExpr{
1017 op: unsafe { token.Token(int(n.aux)) }
1018 start: r.read_expr(r.edge(n, 0))
1019 end: r.read_expr(r.edge(n, 1))
1020 pos: n.pos
1021 })
1022 }
1023 .expr_select {
1024 stmt := r.read_stmt(r.edge(n, 0))
1025 next := r.read_expr(r.edge(n, 1))
1026 mut stmts := []Stmt{cap: n.edge_count - 2}
1027 for i in 2 .. n.edge_count {
1028 stmts << r.read_stmt(r.edge(n, i))
1029 }
1030 return Expr(SelectExpr{
1031 pos: n.pos
1032 stmt: stmt
1033 stmts: stmts
1034 next: next
1035 })
1036 }
1037 .expr_selector {
1038 // s254: read the rhs straight into an Ident; the previous
1039 // `read_expr → if rhs is Ident { rhs }` unbox corrupted the Ident's
1040 // `name` on the arm64 self-host, yielding garbage `missing X.<name>`
1041 // checker errors for selector types like `strings.Builder`.
1042 return Expr(SelectorExpr{
1043 lhs: r.read_expr(r.edge(n, 0))
1044 rhs: r.read_ident(r.edge(n, 1))
1045 pos: n.pos
1046 })
1047 }
1048 .expr_sql {
1049 return Expr(SqlExpr{
1050 expr: r.read_expr(r.edge(n, 0))
1051 table_name: r.get_str(n.name_id)
1052 is_count: (n.flags & flag_is_count) != 0
1053 is_create: (n.flags & flag_is_create) != 0
1054 pos: n.pos
1055 })
1056 }
1057 .expr_string_inter {
1058 values_id := r.edge(n, 0)
1059 inters_id := r.edge(n, 1)
1060 return Expr(StringInterLiteral{
1061 kind: unsafe { StringLiteralKind(int(n.aux)) }
1062 values: r.read_string_list(values_id)
1063 inters: r.read_string_inter_list(inters_id)
1064 pos: n.pos
1065 })
1066 }
1067 .expr_string {
1068 return Expr(StringLiteral{
1069 kind: unsafe { StringLiteralKind(int(n.aux)) }
1070 value: r.get_str(n.name_id)
1071 pos: n.pos
1072 })
1073 }
1074 .expr_tuple {
1075 mut exprs := []Expr{cap: n.edge_count}
1076 for i in 0 .. n.edge_count {
1077 exprs << r.read_expr(r.edge(n, i))
1078 }
1079 return Expr(Tuple{
1080 exprs: exprs
1081 pos: n.pos
1082 })
1083 }
1084 .expr_unsafe {
1085 mut stmts := []Stmt{cap: n.edge_count}
1086 for i in 0 .. n.edge_count {
1087 stmts << r.read_stmt(r.edge(n, i))
1088 }
1089 return Expr(UnsafeExpr{
1090 stmts: stmts
1091 pos: n.pos
1092 })
1093 }
1094 else {
1095 return empty_expr
1096 }
1097 }
1098}
1099
1100fn (r &FlatReader) read_type(id FlatNodeId) Type {
1101 if id < 0 {
1102 return Type(NilType{})
1103 }
1104 n := r.node(id)
1105 match n.kind {
1106 .typ_anon_struct {
1107 generic_params_id := r.edge(n, 0)
1108 embedded_id := r.edge(n, 1)
1109 fields_id := r.edge(n, 2)
1110 return Type(AnonStructType{
1111 generic_params: r.read_expr_list(generic_params_id)
1112 embedded: r.read_expr_list(embedded_id)
1113 fields: r.read_field_decl_list(fields_id)
1114 })
1115 }
1116 .typ_array_fixed {
1117 return Type(ArrayFixedType{
1118 len: r.read_expr(r.edge(n, 0))
1119 elem_type: r.read_expr(r.edge(n, 1))
1120 })
1121 }
1122 .typ_array {
1123 return Type(ArrayType{
1124 elem_type: r.read_expr(r.edge(n, 0))
1125 })
1126 }
1127 .typ_channel {
1128 return Type(ChannelType{
1129 cap: r.read_expr(r.edge(n, 0))
1130 elem_type: r.read_expr(r.edge(n, 1))
1131 })
1132 }
1133 .typ_fn {
1134 generic_params_id := r.edge(n, 0)
1135 params_id := r.edge(n, 1)
1136 return Type(FnType{
1137 generic_params: r.read_expr_list(generic_params_id)
1138 params: r.read_parameter_list(params_id)
1139 return_type: r.read_expr(r.edge(n, 2))
1140 })
1141 }
1142 .typ_generic {
1143 name := r.read_expr(r.edge(n, 0))
1144 mut params := []Expr{cap: n.edge_count - 1}
1145 for i in 1 .. n.edge_count {
1146 params << r.read_expr(r.edge(n, i))
1147 }
1148 return Type(GenericType{
1149 name: name
1150 params: params
1151 })
1152 }
1153 .typ_map {
1154 return Type(MapType{
1155 key_type: r.read_expr(r.edge(n, 0))
1156 value_type: r.read_expr(r.edge(n, 1))
1157 })
1158 }
1159 .typ_nil {
1160 return Type(NilType{})
1161 }
1162 .typ_none {
1163 return Type(NoneType{})
1164 }
1165 .typ_option {
1166 return Type(OptionType{
1167 base_type: r.read_expr(r.edge(n, 0))
1168 })
1169 }
1170 .typ_pointer {
1171 return Type(PointerType{
1172 base_type: r.read_expr(r.edge(n, 0))
1173 lifetime: r.get_str(n.name_id)
1174 })
1175 }
1176 .typ_result {
1177 return Type(ResultType{
1178 base_type: r.read_expr(r.edge(n, 0))
1179 })
1180 }
1181 .typ_thread {
1182 return Type(ThreadType{
1183 elem_type: r.read_expr(r.edge(n, 0))
1184 })
1185 }
1186 .typ_tuple {
1187 mut types := []Expr{cap: n.edge_count}
1188 for i in 0 .. n.edge_count {
1189 types << r.read_expr(r.edge(n, i))
1190 }
1191 return Type(TupleType{
1192 types: types
1193 })
1194 }
1195 else {
1196 return Type(NilType{})
1197 }
1198 }
1199}
1200