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