ruchy/
lib.rs

1//! Ruchy: A modern systems programming language
2//!
3//! Ruchy combines functional programming with systems programming capabilities,
4//! featuring an ML-style syntax, advanced type inference, and zero-cost abstractions.
5#![warn(clippy::all)]
6// Temporarily disabled pedantic for RUCHY-0801 - Re-enable in quality sprint
7// #![warn(clippy::pedantic)]
8#![allow(clippy::module_name_repetitions)]
9#![allow(clippy::must_use_candidate)]
10#![allow(clippy::self_only_used_in_recursion)]
11// Clippy allows for RUCHY-0801 commit - will be addressed in quality sprint
12#![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)] // Single-threaded runtime, Arc used for shared ownership not thread-safety
22// Additional clippy allows for P0 lint fixes
23#![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::*;
106/// Compile Ruchy source code to Rust
107///
108/// # Examples
109///
110/// ```
111/// use ruchy::compile;
112///
113/// let rust_code = compile("42").expect("Failed to compile");
114/// assert!(rust_code.contains("42"));
115/// ```
116///
117/// # Errors
118///
119/// Returns an error if:
120/// - The source code cannot be parsed
121/// - The transpilation to Rust fails
122pub 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    // Use transpile_to_program to wrap in main() for standalone compilation
127    let rust_code = transpiler.transpile_to_program(&ast)?;
128    Ok(rust_code.to_string())
129}
130/// Check if the given source code has valid syntax
131#[must_use]
132pub fn is_valid_syntax(source: &str) -> bool {
133    let mut parser = Parser::new(source);
134    parser.parse().is_ok()
135}
136/// Get parse error details if the source has syntax errors
137#[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/// Run the REPL
143///
144/// # Examples
145///
146/// ```no_run
147/// use ruchy::run_repl;
148///
149/// run_repl().expect("Failed to run REPL");
150/// ```
151///
152/// # Errors
153///
154/// Returns an error if:
155/// - The REPL cannot be initialized
156/// - User interaction fails
157#[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    /// Initialize test configuration once per test run
168    pub fn init() {
169        INIT.call_once(|| {
170            // Limit proptest for development (CI uses different settings)
171            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            // Limit test threads if not already set
176            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        // Array literals should use fixed-size array syntax [1, 2, 3], not vec![1, 2, 3]
222        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        // Error message format may vary, just check that we got an error
429        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 removed - try/catch operations removed in RUCHY-0834
473    // #[test]
474    // fn test_compile_try_operator() {
475    //     let result = compile("func()?").unwrap();
476    //     assert!(result.contains("?"));
477    // }
478    #[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 (")); // Formatted with spaces
507        assert!(result.contains(". await")); // Formatted with spaces
508    }
509    #[test]
510    fn test_compile_ask_operation() {
511        let result = compile("myactor <? request").unwrap();
512        assert!(result.contains(". ask (")); // Formatted with spaces
513        assert!(result.contains(". await")); // Formatted with spaces
514    }
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    // ===== COMPREHENSIVE COVERAGE TESTS =====
538    #[test]
539    fn test_type_conversions() {
540        // String conversions
541        assert!(compile("str(42)").is_ok());
542        assert!(compile("str(3.14)").is_ok());
543        assert!(compile("str(true)").is_ok());
544        // Integer conversions
545        assert!(compile("int(\"42\")").is_ok());
546        assert!(compile("int(3.14)").is_ok());
547        assert!(compile("int(true)").is_ok());
548        // Float conversions
549        assert!(compile("float(\"3.14\")").is_ok());
550        assert!(compile("float(42)").is_ok());
551        // Bool conversions
552        assert!(compile("bool(0)").is_ok());
553        assert!(compile("bool(\"\")").is_ok());
554        assert!(compile("bool([])").is_ok());
555        // Collection conversions
556        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        // String methods
563        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        // List methods
569        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        // Dict methods
575        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        // Iterator methods
580        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        // Literal patterns
587        assert!(compile("match x { 0 => \"zero\", _ => \"other\" }").is_ok());
588        assert!(compile("match x { true => \"yes\", false => \"no\" }").is_ok());
589        // Tuple patterns
590        assert!(compile("match p { (0, 0) => \"origin\", _ => \"other\" }").is_ok());
591        assert!(compile("match p { (x, y) => x + y }").is_ok());
592        // List patterns
593        assert!(compile("match lst { [] => \"empty\", _ => \"has items\" }").is_ok());
594        assert!(compile("match lst { [x] => x, _ => 0 }").is_ok());
595        // Rest patterns syntax not yet supported:
596        // assert!(compile("match lst { [head, ...tail] => head, _ => 0 }").is_ok());
597        // Struct patterns not yet supported:
598        // assert!(compile("match p { Point { x, y } => x + y }").is_ok());
599        // Enum patterns not yet supported:
600        // assert!(compile("match opt { Some(x) => x, None => 0 }").is_ok());
601        assert!(compile("match res { Ok(v) => v, Err(e) => panic(e) }").is_ok());
602        // Guard patterns
603        assert!(compile("match x { n if n > 0 => \"positive\", _ => \"other\" }").is_ok());
604        // Or patterns
605        assert!(compile("match x { 0 | 1 => \"binary\", _ => \"other\" }").is_ok());
606    }
607    #[test]
608    fn test_all_operators() {
609        // Arithmetic
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());
614        assert!(compile("x % y").is_ok());
615        assert!(compile("x ** y").is_ok());
616        // Comparison
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());
621        assert!(compile("x <= y").is_ok());
622        assert!(compile("x >= y").is_ok());
623        // Logical
624        assert!(compile("x && y").is_ok());
625        assert!(compile("x || y").is_ok());
626        assert!(compile("!x").is_ok());
627        // Bitwise
628        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        // Assignment
635        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        // Nullish coalescing works (v1.9.0+)
641        assert!(compile("x ?? y").is_ok());
642        // Optional chaining: tracked in roadmap as LANG-FEAT-001
643        // assert!(compile("x?.y").is_ok());
644    }
645    #[test]
646    fn test_control_flow() {
647        // If statements
648        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        // Loops
652        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        // Break/continue
657        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        // Lists
663        assert!(compile("[]").is_ok());
664        assert!(compile("[1, 2, 3]").is_ok());
665        assert!(compile("[[1, 2], [3, 4]]").is_ok());
666        // Dicts
667        assert!(compile("{}").is_ok());
668        assert!(compile("{\"a\": 1}").is_ok());
669        assert!(compile("{\"a\": 1, \"b\": 2}").is_ok());
670        // Sets - not yet implemented, parser doesn't support set literals
671        // assert!(compile("{1}").is_ok());
672        // assert!(compile("{1, 2, 3}").is_ok());
673        // Tuples
674        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        // Functions
681        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        // Lambdas
686        assert!(compile("|x| x").is_ok());
687        assert!(compile("|x, y| x + y").is_ok());
688        assert!(compile("|| 42").is_ok());
689        // Async fn syntax: tracked in roadmap as LANG-FEAT-002
690        // assert!(compile("async fn f() { await g() }").is_ok());
691        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        // Basic import statements now work
733        assert!(compile("import std").is_ok());
734        assert!(compile("from std import println").is_ok());
735        // JS-style imports still need work
736        // assert!(compile("import { readFile, writeFile } from fs").is_ok());
737        // Export syntax still needs implementation
738        // assert!(compile("export fn helper()").is_ok());
739    }
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        // Empty input - parser expects at least one expression
755        assert!(!is_valid_syntax(""));
756        assert!(!is_valid_syntax("   "));
757        assert!(!is_valid_syntax("\n\n"));
758        // Deeply nested
759        assert!(compile("((((((((((1))))))))))").is_ok());
760        assert!(compile("[[[[[[1]]]]]]").is_ok());
761        // Unicode
762        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        // Test valid syntax
802        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        // Test invalid syntax
809        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        // Just test that these don't panic
826        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        // Even if not supported, shouldn't panic
848        let _ = result;
849    }
850
851    #[test]
852    fn test_compile_loop() {
853        // Loop might not be supported, just test it doesn't panic
854        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        // Async might not be fully supported, just test it doesn't panic
880        let _ = compile("async fn fetch() { await get_data() }");
881    }
882
883    #[test]
884    fn test_compile_various_errors() {
885        // Test various compilation errors
886        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        // Const might not be supported yet, just ensure no panic
954        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        // Test various error conditions
961        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        // Very long identifier
979        let long_id = "a".repeat(1000);
980        let _ = compile(&format!("let {long_id} = 1"));
981
982        // Deeply nested expression - reduced from 100 to 30 to avoid stack overflow
983        let nested = "(".repeat(30) + "1" + &")".repeat(30);
984        let _ = compile(&nested);
985
986        // Many arguments
987        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        /// Property: Function never panics on any input
1099        #[test]
1100        fn test_compile_never_panics(input: String) {
1101            // Limit input size to avoid timeout
1102            let _input = if input.len() > 100 { &input[..100] } else { &input[..] };
1103            // Function should not panic on any input
1104            let _ = std::panic::catch_unwind(|| {
1105                // Call function with various inputs
1106                // This is a template - adjust based on actual function signature
1107            });
1108        }
1109    }
1110}