typed_floats_macros/
add_doc.rs

1use crate::impl_self::get_impl_self;
2use crate::impl_self_rhs::get_impl_self_rhs;
3use crate::types::{OpRhs, ReturnTypeDefinition};
4
5use crate::types::FloatDefinition;
6
7pub fn generate_main_description(floats: &[FloatDefinition]) -> proc_macro2::TokenStream {
8    let mut output: proc_macro2::TokenStream = proc_macro2::TokenStream::new();
9
10    let ops = get_impl_self_rhs();
11
12    output.extend(comment_line(
13        "When the result may be `Nan`, the result type is [`f64`].",
14    ));
15
16    output.extend(generate_fn_table(floats));
17
18    for op in ops {
19        output.extend(generate_op_table(floats, &op));
20    }
21
22    output.extend(comment_line(""));
23
24    output
25}
26
27pub fn comment_line(str: &str) -> proc_macro2::TokenStream {
28    let comment: String = "/// ".to_owned() + str + "\n";
29    comment.parse().expect("Failed to parse comment")
30}
31
32fn line_to_string(line: Vec<String>) -> String {
33    let mut str = "|".to_string();
34    for cell in line {
35        str += cell.as_str();
36        str += "|";
37    }
38
39    str
40}
41
42fn print_table(content: Vec<Vec<String>>) -> proc_macro2::TokenStream {
43    let mut output = proc_macro2::TokenStream::new();
44
45    output.extend(comment_line(""));
46
47    assert!(!content.is_empty());
48
49    let first_line = content[0].clone();
50    let lines = content[1..].to_vec();
51
52    let sep: Vec<String> = first_line.iter().map(|_| "---".to_string()).collect();
53
54    output.extend(comment_line(&line_to_string(first_line)));
55    output.extend(comment_line(&line_to_string(sep)));
56    for line in &lines {
57        output.extend(comment_line(&line_to_string(line.clone())));
58    }
59
60    output.extend(comment_line(""));
61
62    output
63}
64
65fn generate_op_table(floats: &[FloatDefinition], op: &OpRhs) -> proc_macro2::TokenStream {
66    let mut output = proc_macro2::TokenStream::new();
67
68    let mut table: Vec<Vec<String>> = Vec::new();
69
70    let mut header: Vec<String> = Vec::new();
71
72    let mut title: String = op.display.to_string();
73
74    if let Some(comment) = op.comment {
75        let footnote = format!("[^{}]", op.key);
76        title += &footnote;
77        output.extend(comment_line(""));
78        output.extend(comment_line(&(footnote + ": " + comment)));
79    }
80
81    header.push(title);
82    header.extend(floats.iter().map(|float| float.name.to_string()));
83
84    table.push(header);
85
86    for float in floats {
87        let name = float.name;
88        let float_type = float.float_type;
89
90        let mut line: Vec<String> = Vec::new();
91
92        line.push(name.to_string());
93
94        for rhs in floats {
95            let result = op.get_result(float, rhs, floats);
96
97            let result_str = match result {
98                ReturnTypeDefinition::FloatDefinition(result) => result.name,
99                ReturnTypeDefinition::NativeFloat => float_type,
100            };
101            line.push(result_str.to_string());
102        }
103
104        table.push(line);
105    }
106
107    output.extend(print_table(table));
108
109    output
110}
111
112fn generate_fn_table(floats: &[FloatDefinition]) -> proc_macro2::TokenStream {
113    let mut output = proc_macro2::TokenStream::new();
114
115    let mut table: Vec<Vec<String>> = Vec::new();
116
117    let mut header: Vec<String> = Vec::new();
118    header.push(" ".to_string());
119
120    for rhs in floats {
121        header.push(rhs.name.to_string());
122    }
123
124    let ops = get_impl_self();
125
126    table.push(header);
127
128    for op in ops {
129        let mut line: Vec<String> = Vec::new();
130
131        let mut title = op.display.to_string();
132
133        if let Some(comment) = op.comment {
134            let footnote = format!("[^{}]", op.key);
135            title += &footnote;
136            output.extend(comment_line(""));
137            output.extend(comment_line(&(footnote + ": " + comment)));
138        }
139
140        line.push(title);
141
142        for float in floats {
143            let float_type = float.float_type;
144
145            let result = op.get_result(float, floats);
146
147            match result {
148                ReturnTypeDefinition::FloatDefinition(result) => line.push(result.name.to_string()),
149                ReturnTypeDefinition::NativeFloat => line.push(float_type.to_string()),
150            };
151        }
152
153        table.push(line);
154    }
155
156    output.extend(print_table(table));
157
158    output
159}