1use super::*;
5
6pub fn split_subroutines(
8 mut statements: Vec<casl2::Statement>,
9) -> Vec<(String, Vec<casl2::Statement>)> {
10 let mut indexes: Vec<(String, usize)> = vec![];
11
12 for (i, stmt) in statements.iter().enumerate() {
13 let label = if let casl2::Statement::Code {
14 label: Some(label), ..
15 } = stmt
16 {
17 label
18 } else {
19 continue;
20 };
21 let label = label.as_str();
22 if !(label.chars().count() >= 2
23 && label.starts_with('C')
24 && label.chars().skip(1).all(|ch| ch.is_ascii_digit()))
25 {
26 continue;
27 }
28 let label = label.to_string();
29 if let Some(casl2::Statement::Comment { .. }) = statements.get(i - 1) {
30 indexes.push((label, i - 1));
31 } else {
32 indexes.push((label, i));
33 }
34 }
35
36 let mut ret = Vec::<(String, Vec<casl2::Statement>)>::new();
37
38 while let Some((name_label, i)) = indexes.pop() {
39 let routine = statements.split_off(i);
40 let routine = to_external(&name_label, routine);
41 ret.push((name_label, routine));
42 }
43
44 if !matches!(
45 statements.last(),
46 Some(casl2::Statement::Code {
47 command: casl2::Command::End,
48 ..
49 })
50 ) {
51 statements.code(casl2::Command::End);
52 }
53
54 let program_name = casl2::utils::get_program_name(&statements)
55 .unwrap()
56 .to_string();
57
58 ret.push((program_name, statements));
59
60 ret
61}
62
63pub fn to_external(name: &str, mut statements: Vec<casl2::Statement>) -> Vec<casl2::Statement> {
65 if !matches!(
66 statements.last(),
67 Some(casl2::Statement::Code {
68 command: casl2::Command::End,
69 ..
70 })
71 ) {
72 statements.code(casl2::Command::End);
73 }
74
75 for stmt in statements.iter_mut() {
76 if let casl2::Statement::Code { label, .. } = stmt {
77 if matches!(label, Some(label) if label.as_str() == name) {
78 *label = None;
79 break;
80 }
81 }
82 }
83
84 statements.insert(
85 0,
86 casl2::Statement::labeled(name, casl2::Command::Start { entry_point: None }),
87 );
88
89 statements
90}