ryna/
lib.rs

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                // Negative test
96                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                // Positive test
129                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}