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