1#![warn(clippy::all)]
7#![allow(clippy::module_name_repetitions)]
10#![allow(clippy::must_use_candidate)]
11#![allow(clippy::case_sensitive_file_extension_comparisons)]
13#![allow(clippy::match_same_arms)]
14#![allow(clippy::struct_excessive_bools)]
15#![allow(clippy::cast_precision_loss)]
16#![allow(clippy::cast_possible_truncation)]
17#![allow(clippy::unused_self)]
18#![allow(clippy::expect_used)]
19#![allow(clippy::missing_errors_doc)]
20#![allow(clippy::missing_panics_doc)]
21#![allow(clippy::empty_line_after_doc_comments)]
23#![allow(clippy::manual_let_else)]
24#![allow(clippy::redundant_pattern_matching)]
25#![allow(clippy::items_after_statements)]
26#![allow(clippy::too_many_lines)]
27#![allow(clippy::type_complexity)]
28#![allow(dead_code)]
29#![allow(clippy::float_cmp)]
30#![allow(clippy::collapsible_match)]
31#![allow(clippy::cast_sign_loss)]
32#![allow(clippy::manual_strip)]
33#![allow(clippy::implicit_hasher)]
34#![allow(clippy::too_many_arguments)]
35#![allow(clippy::trivially_copy_pass_by_ref)]
36#![allow(clippy::unnecessary_wraps)]
37#![allow(clippy::only_used_in_recursion)]
38#![allow(clippy::print_stdout)]
39#![allow(clippy::print_stderr)]
40#![allow(clippy::format_push_string)]
41#![allow(clippy::field_reassign_with_default)]
42#![allow(clippy::return_self_not_must_use)]
43#![allow(clippy::unwrap_used)]
44#![allow(clippy::needless_pass_by_value)]
45#![allow(clippy::manual_clamp)]
46#![allow(clippy::should_implement_trait)]
47#![allow(clippy::unnecessary_to_owned)]
48#![allow(clippy::cast_possible_wrap)]
49#![allow(clippy::if_same_then_else)]
50
51#[cfg(feature = "mcp")]
52pub mod actors;
53pub mod backend;
54pub mod frontend;
55pub mod lints;
56#[cfg(feature = "mcp")]
57pub mod lsp;
58#[cfg(feature = "mcp")]
59pub mod mcp;
60pub mod middleend;
61pub mod parser;
62pub mod proving;
63pub mod quality;
64pub mod runtime;
65#[cfg(any(test, feature = "testing"))]
66pub mod testing;
67#[cfg(any(test, feature = "testing"))]
68pub use testing::AstBuilder;
69pub mod transpiler;
70pub mod wasm;
71
72#[cfg(feature = "mcp")]
73pub use actors::{
74 Actor, ActorHandle, McpActor, McpMessage, McpResponse, SupervisionStrategy, Supervisor,
75};
76pub use backend::{ModuleResolver, Transpiler};
77pub use backend::wasm::WasmEmitter;
78pub use frontend::ast::{BinaryOp, Expr, ExprKind, Literal, Pattern, UnaryOp};
79pub use frontend::lexer::{Token, TokenStream};
80pub use frontend::parser::Parser;
81#[cfg(feature = "mcp")]
82pub use lsp::{start_server, start_tcp_server, Formatter, RuchyLanguageServer, SemanticAnalyzer};
83pub use quality::{
84 CiQualityEnforcer, CoverageCollector, CoverageReport, CoverageTool, FileCoverage,
85 HtmlReportGenerator, QualityGates, QualityMetrics, QualityReport, QualityThresholds,
86};
87pub use quality::gates::{QualityGateEnforcer, QualityGateConfig, GateResult};
88
89use anyhow::Result;
90
91pub fn compile(source: &str) -> Result<String> {
108 let mut parser = Parser::new(source);
109 let ast = parser.parse()?;
110 let mut transpiler = Transpiler::new();
111 let rust_code = transpiler.transpile_to_program(&ast)?;
113 Ok(rust_code.to_string())
114}
115
116#[must_use]
118pub fn is_valid_syntax(source: &str) -> bool {
119 let mut parser = Parser::new(source);
120 parser.parse().is_ok()
121}
122
123#[must_use]
125pub fn get_parse_error(source: &str) -> Option<String> {
126 let mut parser = Parser::new(source);
127 parser.parse().err().map(|e| e.to_string())
128}
129
130pub fn run_repl() -> Result<()> {
146 let mut repl = runtime::repl::Repl::new()?;
147 repl.run()
148}
149
150#[cfg(test)]
151mod test_config {
152 use std::sync::Once;
153
154 static INIT: Once = Once::new();
155
156 pub fn init() {
158 INIT.call_once(|| {
159 if std::env::var("CI").is_err() {
161 std::env::set_var("PROPTEST_CASES", "10");
162 std::env::set_var("PROPTEST_MAX_SHRINK_ITERS", "50");
163 }
164 if std::env::var("RUST_TEST_THREADS").is_err() {
166 std::env::set_var("RUST_TEST_THREADS", "4");
167 }
168 });
169 }
170}
171
172#[cfg(test)]
173#[allow(clippy::unwrap_used)]
174#[allow(clippy::single_char_pattern)]
175mod tests {
176 use super::test_config;
177 use super::*;
178
179 #[test]
180 fn test_compile_simple() {
181 test_config::init();
182 let result = compile("42").unwrap();
183 assert!(result.contains("42"));
184 }
185
186 #[test]
187 fn test_compile_let() {
188 let result = compile("let x = 10 in x + 1").unwrap();
189 assert!(result.contains("let"));
190 assert!(result.contains("10"));
191 }
192
193 #[test]
194 fn test_compile_function() {
195 let result = compile("fun add(x: i32, y: i32) -> i32 { x + y }").unwrap();
196 assert!(result.contains("fn"));
197 assert!(result.contains("add"));
198 assert!(result.contains("i32"));
199 }
200
201 #[test]
202 fn test_compile_if() {
203 let result = compile("if true { 1 } else { 0 }").unwrap();
204 assert!(result.contains("if"));
205 assert!(result.contains("else"));
206 }
207
208 #[test]
209 fn test_compile_match() {
210 let result = compile("match x { 0 => \"zero\", _ => \"other\" }").unwrap();
211 assert!(result.contains("match"));
212 }
213
214 #[test]
215 fn test_compile_list() {
216 let result = compile("[1, 2, 3]").unwrap();
217 assert!(result.contains("vec") && result.contains("!"));
218 }
219
220 #[test]
221 fn test_compile_lambda() {
222 let result = compile("|x| x * 2").unwrap();
223 assert!(result.contains("|"));
224 }
225
226 #[test]
227 fn test_compile_struct() {
228 let result = compile("struct Point { x: f64, y: f64 }").unwrap();
229 assert!(result.contains("struct"));
230 assert!(result.contains("Point"));
231 }
232
233 #[test]
234 fn test_compile_impl() {
235 let result =
236 compile("impl Point { fun new() -> Point { Point { x: 0.0, y: 0.0 } } }").unwrap();
237 assert!(result.contains("impl"));
238 }
239
240 #[test]
241 fn test_compile_trait() {
242 let result = compile("trait Show { fun show(&self) -> String }").unwrap();
243 assert!(result.contains("trait"));
244 }
245
246 #[test]
247 fn test_compile_for_loop() {
248 let result = compile("for x in [1, 2, 3] { print(x) }").unwrap();
249 assert!(result.contains("for"));
250 }
251
252 #[test]
253 fn test_compile_binary_ops() {
254 let result = compile("1 + 2 * 3 - 4 / 2").unwrap();
255 assert!(result.contains("+"));
256 assert!(result.contains("*"));
257 assert!(result.contains("-"));
258 assert!(result.contains("/"));
259 }
260
261 #[test]
262 fn test_compile_comparison_ops() {
263 let result = compile("x < y && y <= z").unwrap();
264 assert!(result.contains("<"));
265 assert!(result.contains("<="));
266 assert!(result.contains("&&"));
267 }
268
269 #[test]
270 fn test_compile_unary_ops() {
271 let result = compile("-x").unwrap();
272 assert!(result.contains("-"));
273
274 let result = compile("!flag").unwrap();
275 assert!(result.contains("!"));
276 }
277
278 #[test]
279 fn test_compile_call() {
280 let result = compile("func(1, 2, 3)").unwrap();
281 assert!(result.contains("func"));
282 assert!(result.contains("("));
283 assert!(result.contains(")"));
284 }
285
286 #[test]
287 fn test_compile_method_call() {
288 let result = compile("obj.method()").unwrap();
289 assert!(result.contains("."));
290 assert!(result.contains("method"));
291 }
292
293 #[test]
294 fn test_compile_block() {
295 let result = compile("{ let x = 1; x + 1 }").unwrap();
296 assert!(result.contains("{"));
297 assert!(result.contains("}"));
298 }
299
300 #[test]
301 fn test_compile_string() {
302 let result = compile("\"hello world\"").unwrap();
303 assert!(result.contains("hello world"));
304 }
305
306 #[test]
307 fn test_compile_bool() {
308 let result = compile("true && false").unwrap();
309 assert!(result.contains("true"));
310 assert!(result.contains("false"));
311 }
312
313 #[test]
314 fn test_compile_unit() {
315 let result = compile("()").unwrap();
316 assert!(result.contains("()"));
317 }
318
319 #[test]
320 fn test_compile_nested_let() {
321 let result = compile("let x = 1 in let y = 2 in x + y").unwrap();
322 assert!(result.contains("let"));
323 }
324
325 #[test]
326 fn test_compile_nested_if() {
327 let result = compile("if x { if y { 1 } else { 2 } } else { 3 }").unwrap();
328 assert!(result.contains("if"));
329 }
330
331 #[test]
332 fn test_compile_empty_list() {
333 let result = compile("[]").unwrap();
334 assert!(result.contains("vec") && result.contains("!"));
335 }
336
337 #[test]
338 fn test_compile_empty_block() {
339 let result = compile("{ }").unwrap();
340 assert!(result.contains("()"));
341 }
342
343 #[test]
344 fn test_compile_float() {
345 let result = compile("3.14159").unwrap();
346 assert!(result.contains("3.14159"));
347 }
348
349 #[test]
350 fn test_compile_large_int() {
351 let result = compile("999999999").unwrap();
352 assert!(result.contains("999999999"));
353 }
354
355 #[test]
356 fn test_compile_string_escape() {
357 let result = compile(r#""hello\nworld""#).unwrap();
358 assert!(result.contains("hello"));
359 }
360
361 #[test]
362 fn test_compile_power_op() {
363 let result = compile("2 ** 8").unwrap();
364 assert!(result.contains("pow"));
365 }
366
367 #[test]
368 fn test_compile_modulo() {
369 let result = compile("10 % 3").unwrap();
370 assert!(result.contains("%"));
371 }
372
373 #[test]
374 fn test_compile_bitwise_ops() {
375 let result = compile("a & b | c ^ d").unwrap();
376 assert!(result.contains("&"));
377 assert!(result.contains("|"));
378 assert!(result.contains("^"));
379 }
380
381 #[test]
382 fn test_compile_left_shift() {
383 let result = compile("x << 2").unwrap();
384 assert!(result.contains("<<"));
385 }
386
387 #[test]
388 fn test_compile_not_equal() {
389 let result = compile("x != y").unwrap();
390 assert!(result.contains("!="));
391 }
392
393 #[test]
394 fn test_compile_greater_ops() {
395 let result = compile("x > y && x >= z").unwrap();
396 assert!(result.contains(">"));
397 assert!(result.contains(">="));
398 }
399
400 #[test]
401 fn test_compile_or_op() {
402 let result = compile("x || y").unwrap();
403 assert!(result.contains("||"));
404 }
405
406 #[test]
407 fn test_compile_complex_expression() {
408 let result = compile("(x + y) * (z - w) / 2").unwrap();
409 assert!(result.contains("+"));
410 assert!(result.contains("-"));
411 assert!(result.contains("*"));
412 assert!(result.contains("/"));
413 }
414
415 #[test]
416 fn test_compile_errors() {
417 assert!(compile("").is_err());
418 assert!(compile(" ").is_err());
419 assert!(compile("let x =").is_err());
420 assert!(compile("if").is_err());
421 assert!(compile("match").is_err());
422 }
423
424 #[test]
425 fn test_is_valid_syntax_valid_cases() {
426 assert!(is_valid_syntax("42"));
427 assert!(is_valid_syntax("3.14"));
428 assert!(is_valid_syntax("true"));
429 assert!(is_valid_syntax("false"));
430 assert!(is_valid_syntax("\"hello\""));
431 assert!(is_valid_syntax("x + y"));
432 assert!(is_valid_syntax("[1, 2, 3]"));
433 assert!(is_valid_syntax("if true { 1 } else { 2 }"));
434 }
435
436 #[test]
437 fn test_is_valid_syntax_invalid_cases() {
438 assert!(!is_valid_syntax(""));
439 assert!(!is_valid_syntax(" "));
440 assert!(!is_valid_syntax("let x ="));
441 assert!(!is_valid_syntax("if { }"));
442 assert!(!is_valid_syntax("[1, 2,"));
443 assert!(!is_valid_syntax("match"));
444 assert!(!is_valid_syntax("struct"));
445 }
446
447 #[test]
448 fn test_get_parse_error_with_errors() {
449 let error = get_parse_error("fun (");
450 assert!(error.is_some());
451 assert!(!error.unwrap().is_empty());
453 }
454
455 #[test]
456 fn test_get_parse_error_without_errors() {
457 let error = get_parse_error("42");
458 assert!(error.is_none());
459 }
460
461 #[test]
462 fn test_get_parse_error_detailed() {
463 let error = get_parse_error("if");
464 assert!(error.is_some());
465
466 let error = get_parse_error("match");
467 assert!(error.is_some());
468
469 let error = get_parse_error("[1, 2,");
470 assert!(error.is_some());
471 }
472
473 #[test]
474 fn test_compile_generic_function() {
475 let result = compile("fun id<T>(x: T) -> T { x }").unwrap();
476 assert!(result.contains("fn"));
477 assert!(result.contains("id"));
478 }
479
480 #[test]
481 fn test_compile_generic_struct() {
482 let result = compile("struct Box<T> { value: T }").unwrap();
483 assert!(result.contains("struct"));
484 assert!(result.contains("Box"));
485 }
486
487 #[test]
488 fn test_compile_multiple_statements() {
489 let result = compile("let x = 1 in let y = 2 in x + y").unwrap();
490 assert!(result.contains("let"));
491 }
492
493 #[test]
494 fn test_compile_pattern_matching() {
495 let result = compile("match x { 0 => \"zero\", _ => \"other\" }").unwrap();
496 assert!(result.contains("match"));
497 }
498
499 #[test]
500 fn test_compile_struct_literal() {
501 let result = compile("Point { x: 10, y: 20 }").unwrap();
502 assert!(result.contains("Point"));
503 }
504
505 #[test]
513 fn test_compile_await_expression() {
514 let result = compile("async_func().await").unwrap();
515 assert!(result.contains("await"));
516 }
517
518 #[test]
519 fn test_compile_import() {
520 let result = compile("import std.collections.HashMap").unwrap();
521 assert!(result.contains("use"));
522 }
523
524 #[test]
525 fn test_compile_while_loop() {
526 let result = compile("while x < 10 { x + 1 }").unwrap();
527 assert!(result.contains("while"));
528 }
529
530 #[test]
531 fn test_compile_range() {
532 let result = compile("1..10").unwrap();
533 assert!(result.contains(".."));
534 }
535
536 #[test]
537 fn test_compile_pipeline() {
538 let result = compile("data |> filter |> map").unwrap();
539 assert!(result.contains("("));
540 }
541
542 #[test]
543 fn test_compile_send_operation() {
544 let result = compile("myactor <- message").unwrap();
545 assert!(result.contains(". send (")); assert!(result.contains(". await")); }
548
549 #[test]
550 fn test_compile_ask_operation() {
551 let result = compile("myactor <? request").unwrap();
552 assert!(result.contains(". ask (")); assert!(result.contains(". await")); }
555
556 #[test]
557 fn test_compile_list_comprehension() {
558 let result = compile("[x * 2 for x in range(10)]").unwrap();
559 assert!(result.contains("map"));
560 }
561
562 #[test]
563 fn test_compile_actor() {
564 let result = compile(
565 r"
566 actor Counter {
567 count: i32,
568
569 receive {
570 Inc => 1,
571 Get => 0
572 }
573 }
574 ",
575 )
576 .unwrap();
577 assert!(result.contains("struct Counter"));
578 assert!(result.contains("enum CounterMessage"));
579 }
580
581 #[test]
584 fn test_type_conversions() {
585 assert!(compile("str(42)").is_ok());
587 assert!(compile("str(3.14)").is_ok());
588 assert!(compile("str(true)").is_ok());
589
590 assert!(compile("int(\"42\")").is_ok());
592 assert!(compile("int(3.14)").is_ok());
593 assert!(compile("int(true)").is_ok());
594
595 assert!(compile("float(\"3.14\")").is_ok());
597 assert!(compile("float(42)").is_ok());
598
599 assert!(compile("bool(0)").is_ok());
601 assert!(compile("bool(\"\")").is_ok());
602 assert!(compile("bool([])").is_ok());
603
604 assert!(compile("list(\"hello\")").is_ok());
606 assert!(compile("set([1,2,3])").is_ok());
607 assert!(compile("dict([(\"a\",1)])").is_ok());
608 }
609
610 #[test]
611 fn test_method_calls() {
612 assert!(compile("\"hello\".upper()").is_ok());
614 assert!(compile("\"HELLO\".lower()").is_ok());
615 assert!(compile("\" hello \".strip()").is_ok());
616 assert!(compile("\"hello\".len()").is_ok());
617 assert!(compile("\"hello\".split(\" \")").is_ok());
618
619 assert!(compile("[1,2,3].len()").is_ok());
621 assert!(compile("[1,2,3].append(4)").is_ok());
622 assert!(compile("[1,2,3].pop()").is_ok());
623 assert!(compile("[1,2,3].reverse()").is_ok());
624 assert!(compile("[1,2,3].sort()").is_ok());
625
626 assert!(compile("{\"a\":1}.get(\"a\")").is_ok());
628 assert!(compile("{\"a\":1}.keys()").is_ok());
629 assert!(compile("{\"a\":1}.values()").is_ok());
630 assert!(compile("{\"a\":1}.items()").is_ok());
631
632 assert!(compile("[1,2,3].map(|x| x*2)").is_ok());
634 assert!(compile("[1,2,3].filter(|x| x>1)").is_ok());
635 assert!(compile("[1,2,3].reduce(|a,b| a+b)").is_ok());
636 }
637
638 #[test]
639 #[ignore = "Patterns not fully implemented"]
640 fn test_patterns() {
641 assert!(compile("match x { 0 => \"zero\", _ => \"other\" }").is_ok());
643 assert!(compile("match x { true => \"yes\", false => \"no\" }").is_ok());
644
645 assert!(compile("match p { (0, 0) => \"origin\", _ => \"other\" }").is_ok());
647 assert!(compile("match p { (x, y) => x + y }").is_ok());
648
649 assert!(compile("match lst { [] => \"empty\", _ => \"has items\" }").is_ok());
651 assert!(compile("match lst { [x] => x, _ => 0 }").is_ok());
652 assert!(compile("match lst { [head, ...tail] => head, _ => 0 }").is_ok());
653
654 assert!(compile("match p { Point { x, y } => x + y }").is_ok());
656
657 assert!(compile("match opt { Some(x) => x, None => 0 }").is_ok());
659 assert!(compile("match res { Ok(v) => v, Err(e) => panic(e) }").is_ok());
660
661 assert!(compile("match x { n if n > 0 => \"positive\", _ => \"other\" }").is_ok());
663
664 assert!(compile("match x { 0 | 1 => \"binary\", _ => \"other\" }").is_ok());
666 }
667
668 #[test]
669 #[ignore = "Not all operators implemented yet"]
670 fn test_all_operators() {
671 assert!(compile("x + y").is_ok());
673 assert!(compile("x - y").is_ok());
674 assert!(compile("x * y").is_ok());
675 assert!(compile("x / y").is_ok());
676 assert!(compile("x % y").is_ok());
677 assert!(compile("x ** y").is_ok());
678
679 assert!(compile("x == y").is_ok());
681 assert!(compile("x != y").is_ok());
682 assert!(compile("x < y").is_ok());
683 assert!(compile("x > y").is_ok());
684 assert!(compile("x <= y").is_ok());
685 assert!(compile("x >= y").is_ok());
686
687 assert!(compile("x && y").is_ok());
689 assert!(compile("x || y").is_ok());
690 assert!(compile("!x").is_ok());
691
692 assert!(compile("x & y").is_ok());
694 assert!(compile("x | y").is_ok());
695 assert!(compile("x ^ y").is_ok());
696 assert!(compile("~x").is_ok());
697 assert!(compile("x << y").is_ok());
698 assert!(compile("x >> y").is_ok());
699
700 assert!(compile("x = 5").is_ok());
702 assert!(compile("x += 5").is_ok());
703 assert!(compile("x -= 5").is_ok());
704 assert!(compile("x *= 5").is_ok());
705 assert!(compile("x /= 5").is_ok());
706
707 assert!(compile("x ?? y").is_ok());
709 assert!(compile("x?.y").is_ok());
710 }
711
712 #[test]
713 #[ignore = "Control flow not fully implemented"]
714 fn test_control_flow() {
715 assert!(compile("if x { 1 }").is_ok());
717 assert!(compile("if x { 1 } else { 2 }").is_ok());
718 assert!(compile("if x { 1 } else if y { 2 } else { 3 }").is_ok());
719
720 assert!(compile("while x { y }").is_ok());
722 assert!(compile("loop { break }").is_ok());
723 assert!(compile("for i in 0..10 { }").is_ok());
724 assert!(compile("for i in items { }").is_ok());
725
726 assert!(compile("while true { break }").is_ok());
728 assert!(compile("for i in 0..10 { continue }").is_ok());
729 }
730
731 #[test]
732 #[ignore = "Data structures not fully implemented"]
733 fn test_data_structures() {
734 assert!(compile("[]").is_ok());
736 assert!(compile("[1, 2, 3]").is_ok());
737 assert!(compile("[[1, 2], [3, 4]]").is_ok());
738
739 assert!(compile("{}").is_ok());
741 assert!(compile("{\"a\": 1}").is_ok());
742 assert!(compile("{\"a\": 1, \"b\": 2}").is_ok());
743
744 assert!(compile("{1}").is_ok());
746 assert!(compile("{1, 2, 3}").is_ok());
747
748 assert!(compile("()").is_ok());
750 assert!(compile("(1,)").is_ok());
751 assert!(compile("(1, 2, 3)").is_ok());
752 }
753
754 #[test]
755 #[ignore = "Functions not fully implemented"]
756 fn test_functions_lambdas() {
757 assert!(compile("fn f() { }").is_ok());
759 assert!(compile("fn f(x) { x }").is_ok());
760 assert!(compile("fn f(x, y) { x + y }").is_ok());
761 assert!(compile("fn f(x: int) -> int { x }").is_ok());
762
763 assert!(compile("|x| x").is_ok());
765 assert!(compile("|x, y| x + y").is_ok());
766 assert!(compile("|| 42").is_ok());
767
768 assert!(compile("async fn f() { await g() }").is_ok());
770 assert!(compile("await fetch(url)").is_ok());
771 }
772
773 #[test]
774 fn test_string_interpolation() {
775 assert!(compile("f\"Hello {name}\"").is_ok());
776 assert!(compile("f\"x = {x}, y = {y}\"").is_ok());
777 assert!(compile("f\"Result: {calculate()}\"").is_ok());
778 }
779
780 #[test]
781 #[ignore = "Comprehensions not fully implemented"]
782 fn test_comprehensions() {
783 assert!(compile("[x * 2 for x in 0..10]").is_ok());
784 assert!(compile("[x for x in items if x > 0]").is_ok());
785 assert!(compile("{x: x*x for x in 0..5}").is_ok());
786 assert!(compile("{x for x in items if unique(x)}").is_ok());
787 }
788
789 #[test]
790 #[ignore = "Destructuring not fully implemented"]
791 fn test_destructuring() {
792 assert!(compile("let [a, b, c] = [1, 2, 3]").is_ok());
793 assert!(compile("let {x, y} = point").is_ok());
794 assert!(compile("let [head, ...tail] = list").is_ok());
795 assert!(compile("let (a, b) = (1, 2)").is_ok());
796 }
797
798 #[test]
799 #[ignore = "Error handling not fully implemented"]
800 fn test_error_handling() {
801 assert!(compile("try { risky() } catch e { handle(e) }").is_ok());
802 assert!(compile("result?").is_ok());
803 assert!(compile("result.unwrap()").is_ok());
804 assert!(compile("result.expect(\"failed\")").is_ok());
805 assert!(compile("result.unwrap_or(default)").is_ok());
806 }
807
808 #[test]
809 #[ignore = "Classes/structs not fully implemented"]
810 fn test_classes_structs() {
811 assert!(compile("struct Point { x: int, y: int }").is_ok());
812 assert!(compile("class Calculator { fn add(x, y) { x + y } }").is_ok());
813 assert!(compile("enum Option { Some(value), None }").is_ok());
814 }
815
816 #[test]
817 #[ignore = "Imports not fully implemented"]
818 fn test_imports() {
819 assert!(compile("import std").is_ok());
820 assert!(compile("from std import println").is_ok());
821 assert!(compile("import { readFile, writeFile } from fs").is_ok());
822 assert!(compile("export fn helper()").is_ok());
823 }
824
825 #[test]
826 fn test_decorators() {
827 assert!(compile("@memoize\nfn expensive(n) { }").is_ok());
828 assert!(compile("@derive(Debug, Clone)\nstruct Data { }").is_ok());
829 }
830
831 #[test]
832 fn test_generics() {
833 assert!(compile("fn identity<T>(x: T) -> T { x }").is_ok());
834 assert!(compile("struct Pair<T, U> { first: T, second: U }").is_ok());
835 assert!(compile("enum Result<T, E> { Ok(T), Err(E) }").is_ok());
836 }
837
838 #[test]
839 fn test_edge_cases() {
840 assert!(!is_valid_syntax(""));
842 assert!(!is_valid_syntax(" "));
843 assert!(!is_valid_syntax("\n\n"));
844
845 assert!(compile("((((((((((1))))))))))").is_ok());
847 assert!(compile("[[[[[[1]]]]]]").is_ok());
848
849 assert!(compile("\"Hello δΈη\"").is_ok());
851 assert!(compile("\"Emoji π\"").is_ok());
852 }
853
854 #[test]
855 fn test_complex_programs() {
856 let factorial = r"
857 fn factorial(n) {
858 if n <= 1 { 1 } else { n * factorial(n-1) }
859 }
860 ";
861 assert!(compile(factorial).is_ok());
862
863 let fibonacci = r"
864 fn fibonacci(n) {
865 match n {
866 0 => 0,
867 1 => 1,
868 _ => fibonacci(n-1) + fibonacci(n-2)
869 }
870 }
871 ";
872 assert!(compile(fibonacci).is_ok());
873
874 let quicksort = r"
875 fn quicksort(arr) {
876 if arr.len() <= 1 {
877 arr
878 } else {
879 let pivot = arr[0]
880 let less = [x for x in arr[1:] if x < pivot]
881 let greater = [x for x in arr[1:] if x >= pivot]
882 quicksort(less) + [pivot] + quicksort(greater)
883 }
884 }
885 ";
886 assert!(compile(quicksort).is_ok());
887 }
888}