1pub mod builtin;
18pub mod diag;
19pub mod eval;
20pub mod model;
21pub mod ord_map;
22pub mod parse;
23pub mod parser;
24pub mod rc;
25pub mod render;
26pub mod resolve;
27pub mod src_ref;
28pub mod syntax;
29pub mod tree_display;
30pub mod ty;
31pub mod value;
32
33pub type Id = compact_str::CompactString;
35
36#[cfg(test)]
38#[ctor::ctor]
39fn init() {
40 env_logger::init();
41}
42
43const MICROCAD_EXTENSIONS: &[&str] = &["µcad", "mcad", "ucad"];
44
45#[macro_export]
50macro_rules! parse {
51 ($ty:path, $rule:path, $code:expr) => {
52 $crate::parser::Parser::parse_rule::<$ty>($rule, $code, 0).expect("bad inline code")
53 };
54}
55
56#[test]
57fn parse_macro() {
58 let y3 = 3;
59 let p = parse!(
60 syntax::ParameterList,
61 parser::Rule::parameter_list,
62 &format!("(x=0,y=[1,2,{y3},4],z=2)")
63 );
64 assert_eq!(p.to_string(), "x = 0, y = [1, 2, 3, 4], z = 2");
65}
66
67pub fn shorten(what: &str, max_chars: usize) -> String {
69 let short: String = what
70 .chars()
71 .enumerate()
72 .filter_map(|(p, ch)| {
73 if p == max_chars {
74 Some('…')
75 } else if p < max_chars {
76 if ch == '\n' {
77 Some('⏎')
78 } else {
79 Some(ch)
80 }
81 } else {
82 None
83 }
84 })
85 .collect();
86
87 if cfg!(feature = "ansi-color") && short.contains('\x1b') {
88 short + "\x1b[0m"
89 } else {
90 short
91 }
92}
93
94#[macro_export]
96macro_rules! shorten {
97 ($what:expr) => {
98 $crate::shorten(&format!("{}", $what), 140)
99 };
100 ($what:expr,$shorten:expr) => {
101 if $shorten {
102 $crate::shorten!($what)
103 } else {
104 $what
105 }
106 };
107 ($what:expr, $max_chars:literal) => {
108 shorten(format!("{}", $what).lines(), max_chars)
109 };
110}
111
112#[cfg(feature = "ansi-color")]
114#[macro_export]
115macro_rules! mark {
116 (FOUND) => {
117 color_print::cformat!("<G!,k,s> FOUND </>")
118 };
119 (FOUND_INTERIM) => {
120 color_print::cformat!("<W!,k,s> FOUND </>")
121 };
122 (MATCH) => {
123 color_print::cformat!("<Y!,k,s> MATCH </>")
124 };
125 (CALL) => {
126 color_print::cformat!("<B,k,s> CALL </>")
127 };
128 (LOOKUP) => {
129 color_print::cformat!("<c,s>LOOKUP</>")
130 };
131 (LOAD) => {
132 color_print::cformat!("<Y,k,s> LOADING </>")
133 };
134 (RESOLVE) => {
135 color_print::cformat!("<M,k,s> RESOLVE </>")
136 };
137 (AMBIGUOUS) => {
138 color_print::cformat!("<R,k,s> AMBIGUOUS </>")
139 };
140 (NOT_FOUND) => {
141 color_print::cformat!("<R,k,s> NOT FOUND </>")
142 };
143 (NOT_FOUND_INTERIM) => {
144 color_print::cformat!("<Y,k,s> NOT FOUND </>")
145 };
146}
147
148#[cfg(not(feature = "ansi-color"))]
149#[macro_export]
150macro_rules! found {
151 (FOUND) => {
152 "Found"
153 };
154 (FINAL) => {
155 "Found"
156 };
157 (INTERMEDIATE) => {
158 "Found"
159 };
160 (MATCH) => {
161 "Match"
162 };
163 (CALL) => {
164 "Call"
165 };
166 (LOOKUP) => {
167 "Lookup"
168 };
169 (LOAD) => {
170 "Loading"
171 };
172 (RESOLVE) => {
173 "Resolve"
174 };
175 (AMBIGUOUS) => {
176 "Ambiguous"
177 };
178 (NOT_FOUND) => {
179 "Not found"
180 };
181 (NOT_FOUND_INTERIM) => {
182 "Not found"
183 };
184}
185
186#[cfg(feature = "ansi-color")]
188#[macro_export]
189macro_rules! invalid {
190 (VALUE) => {
191 color_print::cstr!("<R!,k,s> NO VALUE </>")
192 };
193 (TYPE) => {
194 color_print::cstr!("<R!,k,s> INVALID TYPE </>")
195 };
196 (OUTPUT) => {
197 color_print::cstr!("<R!,k,s> INVALID OUTPUT </>")
198 };
199 (STACK) => {
200 color_print::cstr!("<W,k,s> EMPTY STACK </>")
201 };
202 (REF) => {
203 color_print::cstr!("<Y!,k,s> NO REF </>")
204 };
205 (FILE) => {
206 color_print::cstr!("<Y!,k,s> NO FILE </>")
207 };
208 (RESULT) => {
209 color_print::cstr!("<Y!,k,s> NO RESULT </>")
210 };
211 (LINE) => {
212 color_print::cstr!("<Y!,k,s> NO LINE </>")
213 };
214 (SOURCE) => {
215 color_print::cstr!("<C!,k,s> FROM STR </>")
216 };
217 (UNKNOWN) => {
218 color_print::cstr!("<M!,k,s> UNKNOWN </>")
219 };
220 (ID) => {
221 color_print::cstr!("<M!,k,s> NO ID </>")
222 };
223 (NAME) => {
224 color_print::cstr!("<M!,k,s> NO NAME </>")
225 };
226 (EXPRESSION) => {
227 color_print::cstr!("<R!,k,s> INVALID EXPRESSION </>")
228 };
229}
230
231#[macro_export]
233macro_rules! invalid_no_ansi {
234 (VALUE) => {
235 "<NO VALUE>"
236 };
237 (TYPE) => {
238 "<INVALID TYPE>"
239 };
240 (OUTPUT) => {
241 "<INVALID OUTPUT>"
242 };
243 (STACK) => {
244 "<INVALID STACK>"
245 };
246 (REF) => {
247 "<INVALID REF>"
248 };
249 (FILE) => {
250 "<INVALID FILE>"
251 };
252 (RESULT) => {
253 "<INVALID RESULT>"
254 };
255 (LINE) => {
256 "<INVALID LINE>"
257 };
258 (SOURCE) => {
259 "<FROM STR>"
260 };
261 (UNKNOWN) => {
262 "<INVALID UNKNOWN>"
263 };
264 (ID) => {
265 "<NO ID>"
266 };
267 (NAME) => {
268 "<INVALID NAME>"
269 };
270 (EXPRESSION) => {
271 "<INVALID EXPRESSION>"
272 };
273}
274
275#[cfg(not(feature = "ansi-color"))]
276macro_rules! invalid {
277 ($x:literal) => {
278 invalid_no_ansi!($x)
279 };
280}