1#![warn(clippy::all)]
6#![allow(clippy::module_name_repetitions)]
9#![allow(clippy::must_use_candidate)]
10#![allow(clippy::self_only_used_in_recursion)]
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#[cfg(feature = "mcp")]
51pub mod actors;
52pub mod api_docs;
53pub mod backend;
54pub mod build_transpiler;
55pub mod cli;
56pub mod debugger;
57pub mod docs;
58pub mod error_recovery_enhanced;
59pub mod frontend;
60pub mod lints;
61#[cfg(feature = "mcp")]
62pub mod lsp;
63pub mod macros;
64#[cfg(feature = "mcp")]
65pub mod mcp;
66pub mod middleend;
67#[cfg(feature = "notebook")]
68pub mod notebook;
69pub mod package;
70pub mod parser;
71pub mod performance_optimizations;
72pub mod proving;
73pub mod quality;
74pub mod runtime;
75pub mod stdlib;
76#[cfg(any(test, feature = "testing"))]
77pub mod testing;
78#[cfg(any(test, feature = "testing"))]
79pub use testing::AstBuilder;
80pub mod transpiler;
81pub mod utils;
82pub mod wasm;
83#[cfg(target_arch = "wasm32")]
84mod wasm_bindings;
85#[cfg(feature = "mcp")]
86pub use actors::{
87 Actor, ActorHandle, McpActor, McpMessage, McpResponse, SupervisionStrategy, Supervisor,
88};
89use anyhow::Result;
90pub use backend::wasm::WasmEmitter;
91pub use backend::{ModuleResolver, Transpiler};
92pub use frontend::ast::{BinaryOp, Expr, ExprKind, Literal, Pattern, UnaryOp};
93pub use frontend::lexer::{Token, TokenStream};
94pub use frontend::parser::Parser;
95#[cfg(feature = "mcp")]
96pub use lsp::{start_server, start_tcp_server, Formatter, RuchyLanguageServer, SemanticAnalyzer};
97pub use quality::gates::{GateResult, QualityGateConfig, QualityGateEnforcer};
98pub use quality::{
99 CiQualityEnforcer, CoverageCollector, CoverageReport, CoverageTool, FileCoverage,
100 HtmlReportGenerator, QualityGates, QualityMetrics, QualityReport, QualityThresholds,
101};
102pub use utils::*;
103pub fn compile(source: &str) -> Result<String> {
120 let mut parser = Parser::new(source);
121 let ast = parser.parse()?;
122 let mut transpiler = Transpiler::new();
123 let rust_code = transpiler.transpile_to_program(&ast)?;
125 Ok(rust_code.to_string())
126}
127#[must_use]
129pub fn is_valid_syntax(source: &str) -> bool {
130 let mut parser = Parser::new(source);
131 parser.parse().is_ok()
132}
133#[must_use]
135pub fn get_parse_error(source: &str) -> Option<String> {
136 let mut parser = Parser::new(source);
137 parser.parse().err().map(|e| e.to_string())
138}
139#[cfg(not(target_arch = "wasm32"))]
155pub fn run_repl() -> Result<()> {
156 let mut repl =
157 runtime::repl::Repl::new(std::env::current_dir().unwrap_or_else(|_| "/tmp".into()))?;
158 repl.run()
159}
160#[cfg(test)]
161mod test_config {
162 use std::sync::Once;
163 static INIT: Once = Once::new();
164 pub fn init() {
166 INIT.call_once(|| {
167 if std::env::var("CI").is_err() {
169 std::env::set_var("PROPTEST_CASES", "10");
170 std::env::set_var("PROPTEST_MAX_SHRINK_ITERS", "50");
171 }
172 if std::env::var("RUST_TEST_THREADS").is_err() {
174 std::env::set_var("RUST_TEST_THREADS", "4");
175 }
176 });
177 }
178}
179#[cfg(test)]
180#[allow(clippy::unwrap_used)]
181#[allow(clippy::single_char_pattern)]
182mod tests {
183 use super::test_config;
184 use super::*;
185 #[test]
186 fn test_compile_simple() {
187 test_config::init();
188 let result = compile("42").expect("Failed to compile literal 42");
189 assert!(result.contains("42"));
190 }
191 #[test]
192 fn test_compile_let() {
193 let result = compile("let x = 10 in x + 1").expect("Failed to compile let expression");
194 assert!(result.contains("let"));
195 assert!(result.contains("10"));
196 }
197 #[test]
198 fn test_compile_function() {
199 let result = compile("fun add(x: i32, y: i32) -> i32 { x + y }").unwrap();
200 assert!(result.contains("fn"));
201 assert!(result.contains("add"));
202 assert!(result.contains("i32"));
203 }
204 #[test]
205 fn test_compile_if() {
206 let result = compile("if true { 1 } else { 0 }").unwrap();
207 assert!(result.contains("if"));
208 assert!(result.contains("else"));
209 }
210 #[test]
211 fn test_compile_match() {
212 let result = compile("match x { 0 => \"zero\", _ => \"other\" }").unwrap();
213 assert!(result.contains("match"));
214 }
215 #[test]
216 fn test_compile_list() {
217 let result = compile("[1, 2, 3]").unwrap();
218 assert!(
220 result.contains("[")
221 && result.contains("1")
222 && result.contains("2")
223 && result.contains("3"),
224 "Expected array syntax, got: {result}"
225 );
226 }
227 #[test]
228 fn test_compile_lambda() {
229 let result = compile("|x| x * 2").unwrap();
230 assert!(result.contains("|"));
231 }
232 #[test]
233 fn test_compile_struct() {
234 let result = compile("struct Point { x: f64, y: f64 }").unwrap();
235 assert!(result.contains("struct"));
236 assert!(result.contains("Point"));
237 }
238 #[test]
239 fn test_compile_impl() {
240 let result =
241 compile("impl Point { fun new() -> Point { Point { x: 0.0, y: 0.0 } } }").unwrap();
242 assert!(result.contains("impl"));
243 }
244 #[test]
245 fn test_compile_trait() {
246 let result = compile("trait Show { fun show(&self) -> String }").unwrap();
247 assert!(result.contains("trait"));
248 }
249 #[test]
250 fn test_compile_for_loop() {
251 let result = compile("for x in [1, 2, 3] { print(x) }").unwrap();
252 assert!(result.contains("for"));
253 }
254 #[test]
255 fn test_compile_binary_ops() {
256 let result = compile("1 + 2 * 3 - 4 / 2").unwrap();
257 assert!(result.contains("+"));
258 assert!(result.contains("*"));
259 assert!(result.contains("-"));
260 assert!(result.contains("/"));
261 }
262 #[test]
263 fn test_compile_comparison_ops() {
264 let result = compile("x < y && y <= z").unwrap();
265 assert!(result.contains("<"));
266 assert!(result.contains("<="));
267 assert!(result.contains("&&"));
268 }
269 #[test]
270 fn test_compile_unary_ops() {
271 let result = compile("-x").unwrap();
272 assert!(result.contains("-"));
273 let result = compile("!flag").unwrap();
274 assert!(result.contains("!"));
275 }
276 #[test]
277 fn test_compile_call() {
278 let result = compile("func(1, 2, 3)").unwrap();
279 assert!(result.contains("func"));
280 assert!(result.contains("("));
281 assert!(result.contains(")"));
282 }
283 #[test]
284 fn test_compile_method_call() {
285 let result = compile("obj.method()").unwrap();
286 assert!(result.contains("."));
287 assert!(result.contains("method"));
288 }
289 #[test]
290 fn test_compile_block() {
291 let result = compile("{ let x = 1; x + 1 }").unwrap();
292 assert!(result.contains("{"));
293 assert!(result.contains("}"));
294 }
295 #[test]
296 fn test_compile_string() {
297 let result = compile("\"hello world\"").unwrap();
298 assert!(result.contains("hello world"));
299 }
300 #[test]
301 fn test_compile_bool() {
302 let result = compile("true && false").unwrap();
303 assert!(result.contains("true"));
304 assert!(result.contains("false"));
305 }
306 #[test]
307 fn test_compile_unit() {
308 let result = compile("()").unwrap();
309 assert!(result.contains("()"));
310 }
311 #[test]
312 fn test_compile_nested_let() {
313 let result = compile("let x = 1 in let y = 2 in x + y").unwrap();
314 assert!(result.contains("let"));
315 }
316 #[test]
317 fn test_compile_nested_if() {
318 let result = compile("if x { if y { 1 } else { 2 } } else { 3 }").unwrap();
319 assert!(result.contains("if"));
320 }
321 #[test]
322 fn test_compile_empty_list() {
323 let result = compile("[]").unwrap();
324 assert!(result.contains("vec") && result.contains("!"));
325 }
326 #[test]
327 fn test_compile_empty_block() {
328 let result = compile("{ }").unwrap();
329 assert!(result.contains("()"));
330 }
331 #[test]
332 fn test_compile_float() {
333 let result = compile("3.14159").unwrap();
334 assert!(result.contains("3.14159"));
335 }
336 #[test]
337 fn test_compile_large_int() {
338 let result = compile("999999999").unwrap();
339 assert!(result.contains("999999999"));
340 }
341 #[test]
342 fn test_compile_string_escape() {
343 let result = compile(r#""hello\nworld""#).unwrap();
344 assert!(result.contains("hello"));
345 }
346 #[test]
347 fn test_compile_power_op() {
348 let result = compile("2 ** 8").unwrap();
349 assert!(result.contains("pow"));
350 }
351 #[test]
352 fn test_compile_modulo() {
353 let result = compile("10 % 3").unwrap();
354 assert!(result.contains("%"));
355 }
356 #[test]
357 fn test_compile_bitwise_ops() {
358 let result = compile("a & b | c ^ d").unwrap();
359 assert!(result.contains("&"));
360 assert!(result.contains("|"));
361 assert!(result.contains("^"));
362 }
363 #[test]
364 fn test_compile_left_shift() {
365 let result = compile("x << 2").unwrap();
366 assert!(result.contains("<<"));
367 }
368 #[test]
369 fn test_compile_not_equal() {
370 let result = compile("x != y").unwrap();
371 assert!(result.contains("!="));
372 }
373 #[test]
374 fn test_compile_greater_ops() {
375 let result = compile("x > y && x >= z").unwrap();
376 assert!(result.contains(">"));
377 assert!(result.contains(">="));
378 }
379 #[test]
380 fn test_compile_or_op() {
381 let result = compile("x || y").unwrap();
382 assert!(result.contains("||"));
383 }
384 #[test]
385 fn test_compile_complex_expression() {
386 let result = compile("(x + y) * (z - w) / 2").unwrap();
387 assert!(result.contains("+"));
388 assert!(result.contains("-"));
389 assert!(result.contains("*"));
390 assert!(result.contains("/"));
391 }
392 #[test]
393 fn test_compile_errors() {
394 assert!(compile("").is_err());
395 assert!(compile(" ").is_err());
396 assert!(compile("let x =").is_err());
397 assert!(compile("if").is_err());
398 assert!(compile("match").is_err());
399 }
400 #[test]
401 fn test_is_valid_syntax_valid_cases() {
402 assert!(is_valid_syntax("42"));
403 assert!(is_valid_syntax("3.14"));
404 assert!(is_valid_syntax("true"));
405 assert!(is_valid_syntax("false"));
406 assert!(is_valid_syntax("\"hello\""));
407 assert!(is_valid_syntax("x + y"));
408 assert!(is_valid_syntax("[1, 2, 3]"));
409 assert!(is_valid_syntax("if true { 1 } else { 2 }"));
410 }
411 #[test]
412 fn test_is_valid_syntax_invalid_cases() {
413 assert!(!is_valid_syntax(""));
414 assert!(!is_valid_syntax(" "));
415 assert!(!is_valid_syntax("let x ="));
416 assert!(!is_valid_syntax("if { }"));
417 assert!(!is_valid_syntax("[1, 2,"));
418 assert!(!is_valid_syntax("match"));
419 assert!(!is_valid_syntax("struct"));
420 }
421 #[test]
422 fn test_get_parse_error_with_errors() {
423 let error = get_parse_error("fun (");
424 assert!(error.is_some());
425 assert!(!error.unwrap().is_empty());
427 }
428 #[test]
429 fn test_get_parse_error_without_errors() {
430 let error = get_parse_error("42");
431 assert!(error.is_none());
432 }
433 #[test]
434 fn test_get_parse_error_detailed() {
435 let error = get_parse_error("if");
436 assert!(error.is_some());
437 let error = get_parse_error("match");
438 assert!(error.is_some());
439 let error = get_parse_error("[1, 2,");
440 assert!(error.is_some());
441 }
442 #[test]
443 fn test_compile_generic_function() {
444 let result = compile("fun id<T>(x: T) -> T { x }").unwrap();
445 assert!(result.contains("fn"));
446 assert!(result.contains("id"));
447 }
448 #[test]
449 fn test_compile_generic_struct() {
450 let result = compile("struct Box<T> { value: T }").unwrap();
451 assert!(result.contains("struct"));
452 assert!(result.contains("Box"));
453 }
454 #[test]
455 fn test_compile_multiple_statements() {
456 let result = compile("let x = 1 in let y = 2 in x + y").unwrap();
457 assert!(result.contains("let"));
458 }
459 #[test]
460 fn test_compile_pattern_matching() {
461 let result = compile("match x { 0 => \"zero\", _ => \"other\" }").unwrap();
462 assert!(result.contains("match"));
463 }
464 #[test]
465 fn test_compile_struct_literal() {
466 let result = compile("Point { x: 10, y: 20 }").unwrap();
467 assert!(result.contains("Point"));
468 }
469 #[test]
476 fn test_compile_await_expression() {
477 let result = compile("async_func().await").unwrap();
478 assert!(result.contains("await"));
479 }
480 #[test]
481 fn test_compile_import() {
482 let result = compile("import std.collections.HashMap").unwrap();
483 assert!(result.contains("use"));
484 }
485 #[test]
486 fn test_compile_while_loop() {
487 let result = compile("while x < 10 { x + 1 }").unwrap();
488 assert!(result.contains("while"));
489 }
490 #[test]
491 fn test_compile_range() {
492 let result = compile("1..10").unwrap();
493 assert!(result.contains(".."));
494 }
495 #[test]
496 fn test_compile_pipeline() {
497 let result = compile("data |> filter |> map").unwrap();
498 assert!(result.contains("("));
499 }
500 #[test]
501 fn test_compile_send_operation() {
502 let result = compile("myactor <- message").unwrap();
503 assert!(result.contains(". send (")); assert!(result.contains(". await")); }
506 #[test]
507 fn test_compile_ask_operation() {
508 let result = compile("myactor <? request").unwrap();
509 assert!(result.contains(". ask (")); assert!(result.contains(". await")); }
512 #[test]
513 fn test_compile_list_comprehension() {
514 let result = compile("[x * 2 for x in range(10)]").unwrap();
515 assert!(result.contains("map"));
516 }
517 #[test]
518 fn test_compile_actor() {
519 let result = compile(
520 r"
521 actor Counter {
522 count: i32,
523 receive {
524 Inc => 1,
525 Get => 0
526 }
527 }
528 ",
529 )
530 .unwrap();
531 assert!(result.contains("struct Counter"));
532 assert!(result.contains("enum CounterMessage"));
533 }
534 #[test]
536 fn test_type_conversions() {
537 assert!(compile("str(42)").is_ok());
539 assert!(compile("str(3.14)").is_ok());
540 assert!(compile("str(true)").is_ok());
541 assert!(compile("int(\"42\")").is_ok());
543 assert!(compile("int(3.14)").is_ok());
544 assert!(compile("int(true)").is_ok());
545 assert!(compile("float(\"3.14\")").is_ok());
547 assert!(compile("float(42)").is_ok());
548 assert!(compile("bool(0)").is_ok());
550 assert!(compile("bool(\"\")").is_ok());
551 assert!(compile("bool([])").is_ok());
552 assert!(compile("list(\"hello\")").is_ok());
554 assert!(compile("set([1,2,3])").is_ok());
555 assert!(compile("dict([(\"a\",1)])").is_ok());
556 }
557 #[test]
558 fn test_method_calls() {
559 assert!(compile("\"hello\".upper()").is_ok());
561 assert!(compile("\"HELLO\".lower()").is_ok());
562 assert!(compile("\" hello \".strip()").is_ok());
563 assert!(compile("\"hello\".len()").is_ok());
564 assert!(compile("\"hello\".split(\" \")").is_ok());
565 assert!(compile("[1,2,3].len()").is_ok());
567 assert!(compile("[1,2,3].append(4)").is_ok());
568 assert!(compile("[1,2,3].pop()").is_ok());
569 assert!(compile("[1,2,3].reverse()").is_ok());
570 assert!(compile("[1,2,3].sort()").is_ok());
571 assert!(compile("{\"a\":1}.get(\"a\")").is_ok());
573 assert!(compile("{\"a\":1}.keys()").is_ok());
574 assert!(compile("{\"a\":1}.values()").is_ok());
575 assert!(compile("{\"a\":1}.items()").is_ok());
576 assert!(compile("[1,2,3].map(|x| x*2)").is_ok());
578 assert!(compile("[1,2,3].filter(|x| x>1)").is_ok());
579 assert!(compile("[1,2,3].reduce(|a,b| a+b)").is_ok());
580 }
581 #[test]
582 fn test_patterns() {
583 assert!(compile("match x { 0 => \"zero\", _ => \"other\" }").is_ok());
585 assert!(compile("match x { true => \"yes\", false => \"no\" }").is_ok());
586 assert!(compile("match p { (0, 0) => \"origin\", _ => \"other\" }").is_ok());
588 assert!(compile("match p { (x, y) => x + y }").is_ok());
589 assert!(compile("match lst { [] => \"empty\", _ => \"has items\" }").is_ok());
591 assert!(compile("match lst { [x] => x, _ => 0 }").is_ok());
592 assert!(compile("match res { Ok(v) => v, Err(e) => panic(e) }").is_ok());
599 assert!(compile("match x { n if n > 0 => \"positive\", _ => \"other\" }").is_ok());
601 assert!(compile("match x { 0 | 1 => \"binary\", _ => \"other\" }").is_ok());
603 }
604 #[test]
605 fn test_all_operators() {
606 assert!(compile("x + y").is_ok());
608 assert!(compile("x - y").is_ok());
609 assert!(compile("x * y").is_ok());
610 assert!(compile("x / y").is_ok());
611 assert!(compile("x % y").is_ok());
612 assert!(compile("x ** y").is_ok());
613 assert!(compile("x == y").is_ok());
615 assert!(compile("x != y").is_ok());
616 assert!(compile("x < y").is_ok());
617 assert!(compile("x > y").is_ok());
618 assert!(compile("x <= y").is_ok());
619 assert!(compile("x >= y").is_ok());
620 assert!(compile("x && y").is_ok());
622 assert!(compile("x || y").is_ok());
623 assert!(compile("!x").is_ok());
624 assert!(compile("x & y").is_ok());
626 assert!(compile("x | y").is_ok());
627 assert!(compile("x ^ y").is_ok());
628 assert!(compile("~x").is_ok());
629 assert!(compile("x << y").is_ok());
630 assert!(compile("x >> y").is_ok());
631 assert!(compile("x = 5").is_ok());
633 assert!(compile("x += 5").is_ok());
634 assert!(compile("x -= 5").is_ok());
635 assert!(compile("x *= 5").is_ok());
636 assert!(compile("x /= 5").is_ok());
637 assert!(compile("x ?? y").is_ok());
639 }
642 #[test]
643 fn test_control_flow() {
644 assert!(compile("if x { 1 }").is_ok());
646 assert!(compile("if x { 1 } else { 2 }").is_ok());
647 assert!(compile("if x { 1 } else if y { 2 } else { 3 }").is_ok());
648 assert!(compile("while x { y }").is_ok());
650 assert!(compile("loop { break }").is_ok());
651 assert!(compile("for i in 0..10 { }").is_ok());
652 assert!(compile("for i in items { }").is_ok());
653 assert!(compile("while true { break }").is_ok());
655 assert!(compile("for i in 0..10 { continue }").is_ok());
656 }
657 #[test]
658 fn test_data_structures() {
659 assert!(compile("[]").is_ok());
661 assert!(compile("[1, 2, 3]").is_ok());
662 assert!(compile("[[1, 2], [3, 4]]").is_ok());
663 assert!(compile("{}").is_ok());
665 assert!(compile("{\"a\": 1}").is_ok());
666 assert!(compile("{\"a\": 1, \"b\": 2}").is_ok());
667 assert!(compile("()").is_ok());
672 assert!(compile("(1,)").is_ok());
673 assert!(compile("(1, 2, 3)").is_ok());
674 }
675 #[test]
676 fn test_functions_lambdas() {
677 assert!(compile("fn f() { }").is_ok());
679 assert!(compile("fn f(x) { x }").is_ok());
680 assert!(compile("fn f(x, y) { x + y }").is_ok());
681 assert!(compile("fn f(x: int) -> int { x }").is_ok());
682 assert!(compile("|x| x").is_ok());
684 assert!(compile("|x, y| x + y").is_ok());
685 assert!(compile("|| 42").is_ok());
686 assert!(compile("await fetch(url)").is_ok());
689 }
690 #[test]
691 fn test_string_interpolation() {
692 assert!(compile("f\"Hello {name}\"").is_ok());
693 assert!(compile("f\"x = {x}, y = {y}\"").is_ok());
694 assert!(compile("f\"Result: {calculate()}\"").is_ok());
695 }
696 #[test]
697 #[ignore = "Comprehensions syntax not yet implemented"]
698 fn test_comprehensions() {
699 assert!(compile("[x * 2 for x in 0..10]").is_ok());
700 assert!(compile("[x for x in items if x > 0]").is_ok());
701 assert!(compile("{x: x*x for x in 0..5}").is_ok());
702 assert!(compile("{x for x in items if unique(x)}").is_ok());
703 }
704 #[test]
705 fn test_destructuring() {
706 assert!(compile("let [a, b, c] = [1, 2, 3]").is_ok());
707 assert!(compile("let {x, y} = point").is_ok());
708 assert!(compile("let [head, ...tail] = list").is_ok());
709 assert!(compile("let (a, b) = (1, 2)").is_ok());
710 }
711 #[test]
712 #[ignore = "Try/catch syntax not yet implemented"]
713 fn test_error_handling() {
714 assert!(compile("try { risky() } catch e { handle(e) }").is_ok());
715 assert!(compile("result?").is_ok());
716 assert!(compile("result.unwrap()").is_ok());
717 assert!(compile("result.expect(\"failed\")").is_ok());
718 assert!(compile("result.unwrap_or(default)").is_ok());
719 }
720 #[test]
721 #[ignore = "Class/struct syntax not yet implemented"]
722 fn test_classes_structs() {
723 assert!(compile("struct Point { x: int, y: int }").is_ok());
724 assert!(compile("class Calculator { fn add(x, y) { x + y } }").is_ok());
725 assert!(compile("enum Option { Some(value), None }").is_ok());
726 }
727 #[test]
728 fn test_imports() {
729 assert!(compile("import std").is_ok());
731 assert!(compile("from std import println").is_ok());
732 }
737 #[test]
738 #[ignore = "Decorator syntax not yet implemented"]
739 fn test_decorators() {
740 assert!(compile("@memoize\nfn expensive(n) { }").is_ok());
741 assert!(compile("@derive(Debug, Clone)\nstruct Data { }").is_ok());
742 }
743 #[test]
744 fn test_generics() {
745 assert!(compile("fn identity<T>(x: T) -> T { x }").is_ok());
746 assert!(compile("struct Pair<T, U> { first: T, second: U }").is_ok());
747 assert!(compile("enum Result<T, E> { Ok(T), Err(E) }").is_ok());
748 }
749 #[test]
750 fn test_edge_cases() {
751 assert!(!is_valid_syntax(""));
753 assert!(!is_valid_syntax(" "));
754 assert!(!is_valid_syntax("\n\n"));
755 assert!(compile("((((((((((1))))))))))").is_ok());
757 assert!(compile("[[[[[[1]]]]]]").is_ok());
758 assert!(compile("\"Hello 世界\"").is_ok());
760 assert!(compile("\"Emoji 😀\"").is_ok());
761 }
762 #[test]
763 #[ignore = "List comprehensions not fully implemented"]
764 fn test_complex_programs() {
765 let factorial = r"
766 fn factorial(n) {
767 if n <= 1 { 1 } else { n * factorial(n-1) }
768 }
769 ";
770 assert!(compile(factorial).is_ok());
771 let fibonacci = r"
772 fn fibonacci(n) {
773 match n {
774 0 => 0,
775 1 => 1,
776 _ => fibonacci(n-1) + fibonacci(n-2)
777 }
778 }
779 ";
780 assert!(compile(fibonacci).is_ok());
781 let quicksort = r"
782 fn quicksort(arr) {
783 if arr.len() <= 1 {
784 arr
785 } else {
786 let pivot = arr[0]
787 let less = [x for x in arr[1:] if x < pivot]
788 let greater = [x for x in arr[1:] if x >= pivot]
789 quicksort(less) + [pivot] + quicksort(greater)
790 }
791 }
792 ";
793 assert!(compile(quicksort).is_ok());
794 }
795
796 #[test]
797 fn test_is_valid_syntax() {
798 assert!(is_valid_syntax("42"));
800 assert!(is_valid_syntax("let x = 10 in x"));
801 assert!(is_valid_syntax("fun f() { }"));
802 assert!(is_valid_syntax("[1, 2, 3]"));
803 assert!(is_valid_syntax("true && false"));
804
805 assert!(!is_valid_syntax("let x ="));
807 assert!(!is_valid_syntax("fun"));
808 assert!(!is_valid_syntax("if { }"));
809 assert!(!is_valid_syntax("match"));
810 }
811
812 #[test]
813 fn test_compile_more_binary_ops() {
814 assert!(compile("10 % 3").is_ok());
815 assert!(compile("2 ** 3").is_ok());
816 assert!(compile("\"a\" < \"b\"").is_ok());
817 assert!(compile("[1] + [2]").is_ok());
818 }
819
820 #[test]
821 fn test_compile_more_unary_ops() {
822 let _ = compile("+42");
824 let _ = compile("-(-42)");
825 }
826
827 #[test]
828 fn test_compile_string_ops() {
829 assert!(compile("\"hello\"").is_ok());
830 assert!(compile("\"hello\" + \" world\"").is_ok());
831 assert!(compile("\"test\".len()").is_ok());
832 }
833
834 #[test]
835 fn test_compile_tuples() {
836 assert!(compile("(1, 2)").is_ok());
837 assert!(compile("(1, \"hello\", true)").is_ok());
838 assert!(compile("(x, y, z)").is_ok());
839 }
840
841 #[test]
842 fn test_compile_do_while() {
843 let result = compile("do { x = x + 1 } while x < 10");
844 let _ = result;
846 }
847
848 #[test]
849 fn test_compile_loop() {
850 let _ = compile("loop { break }");
852 }
853
854 #[test]
855 fn test_compile_comments() {
856 assert!(compile("// This is a comment\n42").is_ok());
857 assert!(compile("/* Block comment */ 42").is_ok());
858 }
859
860 #[test]
861 fn test_compile_float_literals() {
862 assert!(compile("3.14").is_ok());
863 assert!(compile("2.718").is_ok());
864 assert!(compile("0.5").is_ok());
865 assert!(compile("1.0").is_ok());
866 }
867
868 #[test]
869 fn test_compile_bool_literals() {
870 assert!(compile("true").is_ok());
871 assert!(compile("false").is_ok());
872 }
873
874 #[test]
875 fn test_compile_async() {
876 let _ = compile("async fn fetch() { await get_data() }");
878 }
879
880 #[test]
881 fn test_compile_various_errors() {
882 assert!(compile("let x =").is_err());
884 assert!(compile("fun").is_err());
885 assert!(compile("if").is_err());
886 assert!(compile("match x").is_err());
887 assert!(compile("][").is_err());
888 assert!(compile("}{").is_err());
889 }
890
891 #[test]
892 fn test_compile_record() {
893 assert!(compile("{ x: 1, y: 2 }").is_ok());
894 assert!(compile("{ name: \"test\", age: 30 }").is_ok());
895 }
896
897 #[test]
898 fn test_compile_field_access() {
899 assert!(compile("point.x").is_ok());
900 assert!(compile("person.name").is_ok());
901 assert!(compile("obj.method()").is_ok());
902 }
903
904 #[test]
905 fn test_compile_array_index() {
906 assert!(compile("arr[0]").is_ok());
907 assert!(compile("matrix[i][j]").is_ok());
908 }
909
910 #[test]
911 fn test_compile_range_expressions() {
912 assert!(compile("1..10").is_ok());
913 assert!(compile("0..=100").is_ok());
914 }
915
916 #[test]
917 fn test_compile_advanced_patterns() {
918 assert!(compile("match x { Some(v) => v, None => 0 }").is_ok());
919 assert!(compile("match (x, y) { (0, 0) => \"origin\", _ => \"other\" }").is_ok());
920 }
921
922 #[test]
923 fn test_compile_type_annotations() {
924 assert!(compile("let x: i32 = 42").is_ok());
925 assert!(compile("fun f(x: String) -> bool { true }").is_ok());
926 }
927
928 #[test]
929 fn test_compile_generics() {
930 assert!(compile("fun id<T>(x: T) -> T { x }").is_ok());
931 assert!(compile("struct Box<T> { value: T }").is_ok());
932 }
933
934 #[test]
935 fn test_compile_traits() {
936 assert!(compile("trait Show { fun show(self) -> String }").is_ok());
937 assert!(
938 compile("impl Show for i32 { fun show(self) -> String { self.to_string() } }").is_ok()
939 );
940 }
941
942 #[test]
943 fn test_compile_modules() {
944 assert!(compile("mod math { fun add(x: i32, y: i32) -> i32 { x + y } }").is_ok());
945 assert!(compile("use std::collections::HashMap").is_ok());
946 }
947
948 #[test]
949 fn test_compile_const() {
950 let _ = compile("const PI: f64 = 3.14159");
952 let _ = compile("static COUNT: i32 = 0");
953 }
954
955 #[test]
956 fn test_compile_error_handling() {
957 assert!(compile("").is_err() || compile("").is_ok());
959 assert!(compile("(").is_err());
960 assert!(compile(")").is_err());
961 assert!(compile("fun").is_err());
962 assert!(compile("if").is_err());
963 assert!(compile("match").is_err());
964 }
965
966 #[test]
967 fn test_compile_unicode() {
968 assert!(compile("let emoji = \"😀\"").is_ok());
969 assert!(compile("let chinese = \"你好\"").is_ok());
970 assert!(compile("let arabic = \"مرحبا\"").is_ok());
971 }
972
973 #[test]
974 fn test_compile_edge_cases() {
975 let long_id = "a".repeat(1000);
977 let _ = compile(&format!("let {long_id} = 1"));
978
979 let nested = "(".repeat(30) + "1" + &")".repeat(30);
981 let _ = compile(&nested);
982
983 let args = (0..100)
985 .map(|i| format!("arg{i}"))
986 .collect::<Vec<_>>()
987 .join(", ");
988 let _ = compile(&format!("fun f({args}) {{ }}"));
989 }
990
991 #[test]
992 fn test_transpile_direct() {
993 use crate::backend::transpiler::Transpiler;
994 use crate::frontend::parser::Parser;
995
996 let mut parser = Parser::new("1 + 2");
997 if let Ok(ast) = parser.parse() {
998 let transpiler = Transpiler::new();
999 let _ = transpiler.transpile(&ast);
1000 }
1001 }
1002
1003 #[test]
1004 fn test_type_inference_direct() {
1005 use crate::frontend::parser::Parser;
1006 use crate::middleend::infer::InferenceContext;
1007
1008 let mut ctx = InferenceContext::new();
1009 let mut parser = Parser::new("42");
1010 if let Ok(ast) = parser.parse() {
1011 let _ = ctx.infer(&ast);
1012 }
1013 }
1014
1015 #[test]
1016 fn test_interpreter_direct() {
1017 use crate::frontend::parser::Parser;
1018 use crate::runtime::interpreter::Interpreter;
1019
1020 let mut interp = Interpreter::new();
1021 let mut parser = Parser::new("1 + 2");
1022 if let Ok(ast) = parser.parse() {
1023 let _ = interp.eval_expr(&ast);
1024 }
1025 }
1026
1027 #[test]
1028 fn test_repl_commands() {
1029 use crate::runtime::repl::Repl;
1030 use std::path::PathBuf;
1031
1032 let mut repl = Repl::new(PathBuf::from("/tmp")).unwrap();
1033 let _ = repl.eval(":help");
1034 let _ = repl.eval(":clear");
1035 let _ = repl.eval(":exit");
1036 }
1037
1038 #[test]
1039 fn test_module_resolver() {
1040 use crate::backend::module_resolver::ModuleResolver;
1041
1042 let mut resolver = ModuleResolver::new();
1043 resolver.add_search_path(".");
1044 resolver.clear_cache();
1045 let stats = resolver.stats();
1046 assert_eq!(stats.cached_modules, 0);
1047 }
1048
1049 #[test]
1050 fn test_token_types() {
1051 use crate::frontend::lexer::Token;
1052
1053 let t1 = Token::Integer("42".to_string());
1054 let t2 = Token::Identifier("test".to_string());
1055 let t3 = Token::String("hello".to_string());
1056
1057 assert!(matches!(t1, Token::Integer(_)));
1058 assert!(matches!(t2, Token::Identifier(_)));
1059 assert!(matches!(t3, Token::String(_)));
1060 }
1061
1062 #[test]
1063 fn test_value_operations() {
1064 use crate::runtime::Value;
1065 use std::sync::Arc;
1066
1067 let v1 = Value::Integer(42);
1068 let v2 = Value::String(Arc::from("test"));
1069 let v3 = Value::Bool(true);
1070 let v4 = Value::Nil;
1071
1072 assert_eq!(v1.to_string(), "42");
1073 assert_eq!(v2.to_string(), "\"test\"");
1074 assert_eq!(v3.to_string(), "true");
1075 assert_eq!(v4.to_string(), "nil");
1076 }
1077
1078 #[test]
1079 fn test_span_operations() {
1080 use crate::frontend::ast::Span;
1081
1082 let s1 = Span::new(0, 10);
1083 let s2 = Span::new(5, 15);
1084 let merged = s1.merge(s2);
1085
1086 assert_eq!(merged.start, 0);
1087 assert_eq!(merged.end, 15);
1088 }
1089}
1090#[cfg(test)]
1091mod property_tests_lib {
1092 use proptest::proptest;
1093
1094 proptest! {
1095 #[test]
1097 fn test_compile_never_panics(input: String) {
1098 let _input = if input.len() > 100 { &input[..100] } else { &input[..] };
1100 let _ = std::panic::catch_unwind(|| {
1102 });
1105 }
1106 }
1107}