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