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}