luaur_reduce_cli/methods/
reducer_get_nested_stats.rs1use alloc::vec::Vec;
2use luaur_ast::records::ast_stat::AstStat;
3use luaur_ast::records::ast_stat_block::AstStatBlock;
4use luaur_ast::records::ast_stat_for::AstStatFor;
5use luaur_ast::records::ast_stat_for_in::AstStatForIn;
6use luaur_ast::records::ast_stat_function::AstStatFunction;
7use luaur_ast::records::ast_stat_if::AstStatIf;
8use luaur_ast::records::ast_stat_local_function::AstStatLocalFunction;
9use luaur_ast::records::ast_stat_repeat::AstStatRepeat;
10use luaur_ast::records::ast_stat_while::AstStatWhile;
11use luaur_ast::rtti::ast_node_as;
12use luaur_common::macros::luau_assert::LUAU_ASSERT;
13
14use crate::records::reducer::Reducer;
15
16impl Reducer {
17 pub fn get_nested_stats(&self, stat: *mut AstStat) -> Vec<*mut AstStat> {
18 let mut result: Vec<*mut AstStat> = Vec::new();
19
20 let mut append = |block: *mut AstStatBlock| {
21 if !block.is_null() {
22 unsafe {
23 let data = (*block).body.begin();
24 let end = (*block).body.end();
25 let size =
26 (end as usize - data as usize) / core::mem::size_of::<*mut AstStat>();
27 if !data.is_null() && size > 0 {
28 let slice = core::slice::from_raw_parts(data, size);
29 result.extend_from_slice(slice);
30 }
31 }
32 }
33 };
34
35 unsafe {
36 if stat.is_null() {
37 return result;
38 }
39
40 let node_ptr = stat as *mut luaur_ast::records::ast_node::AstNode;
41
42 let block = ast_node_as::<AstStatBlock>(node_ptr);
43 if !block.is_null() {
44 append(block);
45 } else {
46 let ifs = ast_node_as::<AstStatIf>(node_ptr);
47 if !ifs.is_null() {
48 append((*ifs).thenbody);
49 if !(*ifs).elsebody.is_null() {
50 let else_ptr =
51 (*ifs).elsebody as *mut luaur_ast::records::ast_node::AstNode;
52 let else_block = ast_node_as::<AstStatBlock>(else_ptr);
53 if !else_block.is_null() {
54 append(else_block);
55 } else {
56 let else_if = ast_node_as::<AstStatIf>(else_ptr);
57 if !else_if.is_null() {
58 let inner_stats = self.get_nested_stats(else_if as *mut AstStat);
59 result.extend(inner_stats);
60 } else {
61 eprintln!("AstStatIf's else clause can have more statement types than I thought");
62 LUAU_ASSERT!(false);
63 }
64 }
65 }
66 } else {
67 let w = ast_node_as::<AstStatWhile>(node_ptr);
68 if !w.is_null() {
69 append((*w).body);
70 } else {
71 let r = ast_node_as::<AstStatRepeat>(node_ptr);
72 if !r.is_null() {
73 append((*r).body);
74 } else {
75 let f = ast_node_as::<AstStatFor>(node_ptr);
76 if !f.is_null() {
77 append((*f).body);
78 } else {
79 let f_in = ast_node_as::<AstStatForIn>(node_ptr);
80 if !f_in.is_null() {
81 append((*f_in).body);
82 } else {
83 let f_func = ast_node_as::<AstStatFunction>(node_ptr);
84 if !f_func.is_null() {
85 append((*(*f_func).func).body);
86 } else {
87 let f_local = ast_node_as::<AstStatLocalFunction>(node_ptr);
88 if !f_local.is_null() {
89 append((*(*f_local).func).body);
90 }
91 }
92 }
93 }
94 }
95 }
96 }
97 }
98 }
99
100 result
101 }
102}
103
104pub fn reducer_get_nested_stats(this: &Reducer, stat: *mut AstStat) -> Vec<*mut AstStat> {
105 this.get_nested_stats(stat)
106}