1use mimalloc::MiMalloc;
2
3#[global_allocator]
4static GLOBAL: MiMalloc = MiMalloc;
5
6extern crate nom;
7
8#[macro_use]
9extern crate lazy_static;
10
11pub mod cache;
12pub mod patterns;
13pub mod object;
14pub mod operations;
15pub mod functions;
16pub mod types;
17pub mod interfaces;
18pub mod annotations;
19pub mod context;
20pub mod docs;
21
22pub mod debug;
23pub mod parser;
24pub mod macros;
25pub mod inference;
26pub mod checks;
27pub mod compilation;
28pub mod optimization;
29pub mod execution;
30pub mod translation;
31pub mod serialization;
32
33pub mod config;
34
35#[path = "algorithms/regex_ext.rs"]
36pub mod regex_ext;
37
38#[path = "algorithms/html_ext.rs"]
39pub mod html_ext;
40
41#[path = "algorithms/integer_ext.rs"]
42pub mod integer_ext;
43
44#[path = "algorithms/git.rs"]
45pub mod git;
46
47#[path = "algorithms/profiling.rs"]
48pub mod profiling;
49
50#[path = "algorithms/formats.rs"]
51pub mod formats;
52
53#[path = "algorithms/shell.rs"]
54pub mod shell;
55
56#[path = "structures/graph.rs"]
57pub mod graph;
58
59#[path = "structures/variable_map.rs"]
60pub mod variable_map;
61
62#[path = "structures/id_mapper.rs"]
63pub mod id_mapper;
64
65#[path = "structures/precedence_cache.rs"]
66pub mod precedence_cache;
67
68#[path = "structures/mut_cell.rs"]
69pub mod mut_cell;
70
71#[cfg(test)]
72mod integration {
73 use std::fs::read_to_string;
74 use crate::compilation::RynaError;
75 use crate::context::standard_ctx;
76 use crate::config::{precompile_ryna_module_with_config, compute_project_hash};
77 use crate::functions::define_macro_emit_fn;
78 use glob::glob;
79
80 fn integration_test(file_path: &str) {
81 let file = read_to_string(file_path).expect("Unable to locate file");
82 let mut ctx = standard_ctx();
83 ctx.optimize = true;
84
85 if let Err(err) = ctx.parse_and_execute_ryna_module(&file) {
86 err.emit();
87 }
88 }
89
90 fn integration_test_batch(glob_path: &str) {
91 for file_path in glob(glob_path).expect("Invalid glob") {
92 let file = read_to_string(file_path.unwrap()).expect("Unable to locate file");
93
94 if file.starts_with("// ") {
95 let expected_msg = &file.lines().next().unwrap()[3..];
97
98 let result = std::panic::catch_unwind(|| {
99 let mut ctx = standard_ctx();
100 ctx.optimize = true;
101
102 ctx.parse_and_execute_ryna_module(&file)
103
104 }).unwrap_or_else(|err| {
105 Err(RynaError::execution_error(panic_message::panic_message(&err).to_owned()))
106 });
107
108 if let Err(err) = result {
109 let exp_chars = expected_msg.chars().collect::<Vec<_>>();
110 let err_chars = err.message.chars().collect::<Vec<_>>();
111 let mut exp_idx = 0;
112 let mut err_idx = 0;
113
114 while exp_idx < exp_chars.len() && err_idx < err_chars.len() {
115 exp_idx += (err_chars[err_idx] == exp_chars[exp_idx]) as usize;
116 err_idx += 1;
117 }
118
119 if exp_idx != exp_chars.len() {
120 panic!("Error message was different from expected:\n - Expected: {}\n - Got: {}", expected_msg, err.message);
121 }
122
123 } else {
124 panic!("Test did not fail!");
125 }
126
127 } else {
128 let mut ctx = standard_ctx();
130 define_macro_emit_fn(&mut ctx, "emit".into());
131
132 if let Err(err) = ctx.parse_and_execute_ryna_module(&file) {
133 err.emit();
134 }
135
136 if file.starts_with("/// ") {
137 let expected_msg = &file.lines().next().unwrap()[4..];
138
139 let exp_chars = expected_msg.chars().collect::<Vec<_>>();
140 let msg_chars = ctx.captured_output.borrow().chars().collect::<Vec<_>>();
141 let mut exp_idx = 0;
142 let mut msg_idx = 0;
143
144 while exp_idx < exp_chars.len() && msg_idx < msg_chars.len() {
145 exp_idx += (msg_chars[msg_idx] == exp_chars[exp_idx]) as usize;
146 msg_idx += 1;
147 }
148
149 if exp_idx != exp_chars.len() {
150 panic!("Captured output was different from expected:\n - Expected: {}\n - Got: {}", expected_msg, ctx.captured_output.borrow());
151 }
152 }
153 }
154 }
155 }
156
157 fn module_test(module_path: &str) {
158 let path_str = &module_path.to_string();
159 let (_, all_mods, files) = compute_project_hash(path_str, None, true, false).unwrap();
160 let err = precompile_ryna_module_with_config(path_str, all_mods, files, true, false, true);
161
162 if let Err(err) = &err {
163 err.emit();
164 }
165
166 let (mut ctx, lines) = err.unwrap();
167
168 match ctx.compiled_form(&lines) {
169 Ok(mut code) => {
170 ctx.optimize_instructions(&mut code);
171
172 for (idx, i) in code.iter().enumerate() {
173 println!("{:<3} {}", idx, i.to_string(&ctx));
174 }
175
176 if let Err(err) = ctx.execute_compiled_code::<false>(&code.into_iter().map(|i| i.instruction).collect::<Vec<_>>(), &[]) {
177 err.emit();
178 }
179 },
180
181 Err(err) => err.emit()
182 };
183 }
184
185 #[test]
186 fn naive_primality() {
187 integration_test("test/primality.ryna");
188 }
189
190 #[test]
191 fn mapped_iterator() {
192 integration_test("test/mapped_iterator.ryna");
193 }
194
195 #[test]
196 fn dice() {
197 integration_test("test/dice.ryna");
198 }
199
200 #[test]
201 fn ints_custom_syntax() {
202 integration_test("test/ints.ryna");
203 }
204
205 #[test]
206 fn random() {
207 integration_test("test/random.ryna");
208 }
209
210 #[test]
211 fn tuples() {
212 integration_test("test/tuples.ryna");
213 }
214
215 #[test]
216 fn array_access() {
217 integration_test("test/array_access.ryna");
218 }
219
220 #[test]
221 fn array_init() {
222 integration_test("test/array_init.ryna");
223 }
224
225 #[test]
226 fn list_comprehension() {
227 integration_test("test/list_comprehension.ryna");
228 }
229
230 #[test]
231 fn map_array() {
232 integration_test("test/map_array.ryna");
233 }
234
235 #[test]
236 fn array_transform() {
237 integration_test("test/array_transform.ryna");
238 }
239
240 #[test]
241 fn e_approximation() {
242 integration_test("test/e_approximation.ryna");
243 }
244
245 #[test]
246 fn basic_alias() {
247 integration_test("test/basic_alias.ryna");
248 }
249
250 #[test]
251 fn adt_list() {
252 integration_test("test/adt_list.ryna");
253 }
254
255 #[test]
256 fn adt_generic_list() {
257 integration_test("test/adt_generic_list.ryna");
258 }
259
260 #[test]
261 fn adt_bin_tree() {
262 integration_test("test/adt_bin_tree.ryna");
263 }
264
265 #[test]
266 fn numeric_interface() {
267 integration_test("test/numeric_interface.ryna");
268 }
269
270 #[test]
271 fn parametric_interface() {
272 integration_test("test/parametric_interface.ryna");
273 }
274
275 #[test]
276 fn peano_arithmetic() {
277 integration_test("test/peano_arithmetic.ryna");
278 }
279
280 #[test]
281 fn short_circuit() {
282 integration_test("test/short_circuit.ryna");
283 }
284
285 #[test]
286 fn file_manip() {
287 integration_test("test/file_manip.ryna");
288 }
289
290 #[test]
291 fn string_manip() {
292 integration_test("test/string_manip.ryna");
293 }
294
295 #[test]
296 fn ambiguous_impl() {
297 integration_test("test/ambiguous_impl.ryna");
298 }
299
300 #[test]
301 fn ternary() {
302 integration_test("test/ternary.ryna");
303 }
304
305 #[test]
306 fn adt_assignment() {
307 integration_test("test/adt_assignment.ryna");
308 }
309
310 #[test]
311 fn bitwise() {
312 integration_test("test/bitwise.ryna");
313 }
314
315 #[test]
316 fn rdl_macros() {
317 integration_test("test/rdl_macros.ryna");
318 }
319
320 #[test]
321 fn do_blocks() {
322 integration_test("test/do_blocks.ryna");
323 }
324
325 #[test]
326 fn break_loops() {
327 integration_test("test/break_loops.ryna");
328 }
329
330 #[test]
331 fn continue_loops() {
332 integration_test("test/continue_loops.ryna");
333 }
334
335 #[test]
336 fn lambda_capture() {
337 integration_test("test/lambda_capture.ryna");
338 }
339
340 #[test]
341 fn unicode() {
342 integration_test("test/unicode.ryna");
343 }
344
345 #[test]
346 fn implicit_lambda() {
347 integration_test("test/implicit_lambda.ryna");
348 }
349
350 #[test]
351 fn exp_floats() {
352 integration_test("test/exp_floats.ryna");
353 }
354
355 #[test]
356 fn destructors() {
357 integration_test("test/destructors.ryna");
358 }
359
360 #[test]
361 fn static_vars() {
362 integration_test("test/static_vars.ryna");
363 }
364
365 #[test]
366 fn lambdas() {
367 integration_test("test/lambdas.ryna");
368 }
369
370 #[test]
371 fn moving() {
372 integration_test_batch("test/batches/moving/*.ryna");
373 }
374
375 #[test]
376 fn interfaces() {
377 integration_test_batch("test/batches/interfaces/*.ryna");
378 }
379
380 #[test]
381 fn macros() {
382 integration_test_batch("test/batches/macros/*.ryna");
383 }
384
385 #[test]
386 fn stack() {
387 integration_test_batch("test/batches/stack/*.ryna");
388 }
389
390 #[test]
391 fn destructors_batch() {
392 integration_test_batch("test/batches/destructors/*.ryna");
393 }
394
395 #[test]
396 fn sum() {
397 module_test("test/modules/sum");
398 }
399
400 #[test]
401 fn prime_check() {
402 module_test("test/modules/prime_check");
403 }
404
405 #[test]
406 fn prime_streaming() {
407 module_test("test/modules/prime_streaming");
408 }
409
410 #[test]
411 fn props_test() {
412 module_test("test/modules/props_test");
413 }
414
415 #[test]
416 fn math_ops() {
417 module_test("test/modules/math_ops");
418 }
419
420 #[test]
421 fn syntax_test() {
422 module_test("test/modules/syntax_test");
423 }
424
425 #[test]
426 fn hash_extensions() {
427 module_test("test/modules/hash_extensions");
428 }
429
430 #[test]
431 fn hash_structs_test() {
432 module_test("test/modules/hash_structs_test");
433 }
434
435 #[test]
436 fn json_test() {
437 module_test("test/modules/json_test");
438 }
439
440 #[test]
441 fn set_syntax_test() {
442 module_test("test/modules/set_syntax_test");
443 }
444
445 #[test]
446 fn array_algorithms() {
447 module_test("test/modules/array_algorithms");
448 }
449
450 #[test]
451 fn iterators_test() {
452 module_test("test/modules/iterators_test");
453 }
454
455 #[test]
456 fn macro_code_ex() {
457 module_test("test/modules/macro_code_ex");
458 }
459
460 #[test]
461 fn bf_embed() {
462 module_test("test/modules/bf_embed");
463 }
464
465 #[test]
466 fn match_test() {
467 module_test("test/modules/match_test");
468 }
469}