1#![allow(dead_code)]
2
3pub mod elements;
4pub mod indexation;
5pub mod lang_token;
6pub mod operation_priority;
7pub mod type_token;
8pub mod types;
9pub mod vector_priority;
10
11use crate::components::context::config::Config;
12use crate::components::error_message::help_data::HelpData;
13use crate::components::error_message::syntax_error::SyntaxError;
14use crate::components::language::operators::custom_op;
15use crate::components::language::operators::Op;
16use crate::components::language::var::Var;
17use crate::components::language::Lang;
18use crate::components::language::ModulePosition;
19use crate::components::r#type::vector_type::ConstructorCategory;
20use crate::components::r#type::Type;
21use crate::processes::parsing::elements::break_exp;
22use crate::processes::parsing::elements::chars;
23use crate::processes::parsing::elements::next_exp;
24use crate::processes::parsing::elements::parse_elements;
25use crate::processes::parsing::elements::return_exp;
26use crate::processes::parsing::elements::scope;
27use crate::processes::parsing::elements::single_element;
28use crate::processes::parsing::elements::tag_exp;
29use crate::processes::parsing::elements::tuple_exp;
30use crate::processes::parsing::elements::variable;
31use crate::processes::parsing::elements::variable2;
32use crate::processes::parsing::elements::variable_exp;
33use crate::processes::parsing::elements::variable_recognizer;
34use crate::processes::parsing::elements::vector;
35use crate::processes::parsing::elements::Case;
36use crate::processes::parsing::types::ltype;
37use crate::processes::parsing::types::pascal_case_no_space;
38use crate::processes::parsing::types::single_letter_type_alias;
39use crate::processes::parsing::types::type_alias;
40use nom::branch::alt;
41use nom::bytes::complete::tag;
42use nom::bytes::complete::take_while1;
43use nom::character::complete::line_ending;
44use nom::character::complete::multispace0;
45use nom::character::complete::multispace1;
46use nom::character::complete::not_line_ending;
47use nom::combinator::map;
48use nom::combinator::opt;
49use nom::multi::many0;
50use nom::multi::many1;
51use nom::multi::separated_list0;
52use nom::sequence::delimited;
53use nom::sequence::pair;
54use nom::sequence::preceded;
55use nom::sequence::terminated;
56use nom::IResult;
57use nom::Parser;
58use nom_locate::LocatedSpan;
59use std::ops::Deref;
60
61type Span<'a> = LocatedSpan<&'a str, String>;
62
63use std::cell::RefCell;
64
65thread_local! {
66 static PARSE_ERRORS: RefCell<Vec<SyntaxError>> = const { RefCell::new(Vec::new()) };
67}
68
69pub fn push_parse_error(err: SyntaxError) {
70 PARSE_ERRORS.with(|e| e.borrow_mut().push(err));
71}
72
73fn take_parse_errors() -> Vec<SyntaxError> {
74 PARSE_ERRORS.with(|e| e.borrow_mut().drain(..).collect())
75}
76
77#[derive(Debug, Clone)]
79pub struct ParseResult {
80 pub ast: Lang,
81 pub errors: Vec<SyntaxError>,
82}
83
84impl ParseResult {
85 pub fn new(ast: Lang) -> Self {
86 let errors = take_parse_errors();
87 ParseResult { ast, errors }
88 }
89
90 pub fn has_errors(&self) -> bool {
91 !self.errors.is_empty()
92 }
93
94 pub fn get_ast(&self) -> &Lang {
95 &self.ast
96 }
97
98 pub fn get_clean_ast(&self) -> Lang {
99 self.ast.clone()
100 }
101}
102
103fn pattern_var(s: Span) -> IResult<Span, (Vec<Lang>, Option<String>)> {
104 let res = alt((tag_exp, variable2)).parse(s);
105 match res {
106 Ok((s, Lang::Tag { name, value: val, .. })) => {
107 if let Lang::Variable {
108 name: name2,
109 is_opaque: mutopa,
110 related_type: typ,
111 help_data: h,
112 } = *val
113 {
114 Ok((
115 s,
116 (
117 vec![Lang::Variable {
118 name: name2.to_string(),
119 is_opaque: mutopa,
120 related_type: typ,
121 help_data: h.clone(),
122 }],
123 Some(name.to_string()),
124 ),
125 ))
126 } else {
127 Ok((s, (vec![], Some(name.to_string()))))
128 }
129 }
130 Ok((
131 s,
132 Lang::Variable {
133 name,
134 is_opaque: mutopa,
135 related_type: typ,
136 help_data: h,
137 },
138 )) => Ok((
139 s,
140 (
141 vec![Lang::Variable {
142 name,
143 is_opaque: mutopa,
144 related_type: typ,
145 help_data: h.clone(),
146 }],
147 None,
148 ),
149 )),
150 Err(r) => Err(r),
151 _ => todo!(),
152 }
153}
154
155fn single_parse(s: Span) -> IResult<Span, Lang> {
156 let res = (parse_elements, opt(terminated(tag(";"), multispace0))).parse(s);
157 match res {
158 Ok((s, (exp, Some(_)))) => Ok((s, exp)),
159 Ok((s, (exp, None))) => {
160 push_parse_error(SyntaxError::ForgottenSemicolon(exp.clone().into()));
161 Ok((s, exp))
162 }
163 Err(r) => Err(r),
164 }
165}
166
167fn equality_operator(s: Span) -> IResult<Span, Span> {
168 terminated(alt((tag("="), tag("<-"))), multispace0).parse(s)
169}
170
171fn base_let_exp(s: Span) -> IResult<Span, Vec<Lang>> {
172 let res = (
173 terminated(tag("let"), multispace0),
174 pattern_var,
175 opt(preceded(terminated(tag(":"), multispace0), ltype)),
176 equality_operator,
177 single_parse,
178 )
179 .parse(s);
180 match res {
181 Ok((
182 s,
183 (
184 _let,
185 (pat_var, None),
186 typ,
187 _eq,
188 Lang::Function {
189 parameters: params,
190 return_type: ty,
191 body,
192 help_data: h,
193 },
194 ),
195 )) if !params.is_empty() => {
196 let newvar = Var::from_language(pat_var[0].clone())
197 .unwrap()
198 .set_type(params[0].1.clone());
199 if let Lang::Variable { name, help_data, .. } = &pat_var[0] {
200 if name.chars().next().is_some_and(|c| c.is_uppercase()) {
201 push_parse_error(SyntaxError::LetInsteadOfType {
202 name: name.clone(),
203 help_data: help_data.clone(),
204 });
205 }
206 }
207 Ok((
208 s,
209 vec![Lang::Let {
210 variable: Box::new(newvar.to_language()),
211 r#type: typ.unwrap_or(Type::Empty(HelpData::default())),
212 expression: Box::new(Lang::Function {
213 parameters: params,
214 return_type: ty,
215 body,
216 help_data: h,
217 }),
218 is_public: false,
219 is_testable: false,
220 is_export: false,
221 help_data: _let.into(),
222 }],
223 ))
224 }
225 Ok((s, (_let, (pat_var, None), typ, _eq, body))) => {
226 if let Lang::Variable { name, help_data, .. } = &pat_var[0] {
227 if name.chars().next().is_some_and(|c| c.is_uppercase()) {
228 push_parse_error(SyntaxError::LetInsteadOfType {
229 name: name.clone(),
230 help_data: help_data.clone(),
231 });
232 }
233 }
234 Ok((
235 s,
236 vec![Lang::Let {
237 variable: Box::new(pat_var[0].clone()),
238 r#type: typ.clone().unwrap_or(Type::Empty(HelpData::default())),
239 expression: Box::new(body),
240 is_public: false,
241 is_testable: false,
242 is_export: false,
243 help_data: _let.into(),
244 }],
245 ))
246 }
247 Ok((s, (_let, (pat_var, Some(_)), typ, eq, body))) => {
248 if pat_var.len() == 1 {
249 Ok((
250 s,
251 vec![Lang::Let {
252 variable: Box::new(pat_var[0].clone()),
253 r#type: typ.clone().unwrap_or(Type::Empty(HelpData::default())),
254 expression: Box::new(Lang::Operator {
255 operator: Op::Dollar(HelpData::default()),
256 rhs: Box::new(Lang::Number {
257 value: 0.0,
258 help_data: eq.into(),
259 }),
260 lhs: Box::new(body),
261 help_data: pat_var.into(),
262 }),
263 is_public: false,
264 is_testable: false,
265 is_export: false,
266 help_data: _let.into(),
267 }],
268 ))
269 } else {
270 Ok((
271 s,
272 pat_var
273 .iter()
274 .map(|x| Lang::Let {
275 variable: Box::new(x.clone()),
276 r#type: typ.clone().unwrap_or(Type::Empty(HelpData::default())),
277 expression: Box::new(body.clone()),
278 is_public: false,
279 is_testable: false,
280 is_export: false,
281 help_data: HelpData::default(),
282 })
283 .collect::<Vec<_>>(),
284 ))
285 }
286 }
287 Err(r) => Err(r),
288 }
289}
290
291fn let_tuple_exp(s: Span) -> IResult<Span, Vec<Lang>> {
292 let res = (
293 terminated(tag("let"), multispace0),
294 tuple_exp,
295 opt(preceded(terminated(tag(":"), multispace0), ltype)),
296 equality_operator,
297 single_parse,
298 )
299 .parse(s);
300 match res {
301 Ok((
302 s,
303 (
304 _let,
305 Lang::Tuple {
306 value: elements,
307 help_data: _th,
308 },
309 typ,
310 _eq,
311 body,
312 ),
313 )) => {
314 if let Lang::Tuple {
319 value: body_elements, ..
320 } = &body
321 {
322 if elements.len() != body_elements.len() {
323 push_parse_error(SyntaxError::TupleDestructureArityMismatch {
324 expected: elements.len(),
325 found: body_elements.len(),
326 help_data: _th.clone(),
327 });
328 }
329 }
330
331 let tmp_name = "__tuple_tmp__";
332 let tmp_var = Var::from_name(tmp_name).to_language();
333
334 let tmp_let = Lang::Let {
336 variable: Box::new(tmp_var.clone()),
337 r#type: typ.unwrap_or(Type::Empty(HelpData::default())),
338 expression: Box::new(body),
339 is_public: false,
340 is_testable: false,
341 is_export: false,
342 help_data: _let.into(),
343 };
344
345 let mut result = vec![tmp_let];
347 for (i, elem) in elements.iter().enumerate() {
348 if let Lang::Variable { name, .. } = elem {
349 if name == "_" {
350 continue; }
352 }
353 result.push(Lang::Let {
354 variable: Box::new(elem.clone()),
355 r#type: Type::Empty(HelpData::default()),
356 expression: Box::new(Lang::Operator {
357 operator: Op::Dot(HelpData::default()),
358 rhs: Box::new(Lang::Integer {
359 value: (i + 1) as i32,
360 help_data: HelpData::default(),
361 }),
362 lhs: Box::new(tmp_var.clone()),
363 help_data: HelpData::default(),
364 }),
365 is_public: false,
366 is_testable: false,
367 is_export: false,
368 help_data: HelpData::default(),
369 });
370 }
371
372 Ok((s, result))
373 }
374 Ok(_) => unreachable!("tuple_exp always returns Lang::Tuple"),
375 Err(r) => Err(r),
376 }
377}
378
379fn let_exp(s: Span) -> IResult<Span, Vec<Lang>> {
380 let res = (
381 opt(terminated(
382 alt((tag("@export"), tag("@pub"), tag("@testable"))),
383 multispace0,
384 )),
385 base_let_exp,
386 )
387 .parse(s);
388 match res {
389 Ok((s, (None, le))) => Ok((s, le)),
390 Ok((s, (Some(annotation), le))) => {
391 let frag = *annotation.fragment();
395 let is_pub = frag == "@pub" || frag == "@export";
396 let is_test = frag == "@testable" || frag == "@pub" || frag == "@export";
397 let is_exp = frag == "@export";
398 let new_le = le
399 .iter()
400 .map(|x| match x {
401 Lang::Let {
402 variable: var,
403 r#type: typ,
404 expression: body,
405 is_public: _,
406 is_testable: _,
407 is_export: _,
408 help_data: h,
409 } => {
410 let vari = Var::from_language(var.deref().clone()).unwrap().to_language();
411 Lang::Let {
412 variable: Box::new(vari),
413 r#type: typ.clone(),
414 expression: body.clone(),
415 is_public: is_pub,
416 is_testable: is_test,
417 is_export: is_exp,
418 help_data: h.clone(),
419 }
420 }
421 lan => lan.clone(),
422 })
423 .collect();
424 Ok((s, new_le))
425 }
426 Err(r) => Err(r),
427 }
428}
429
430fn typeconstructor_exp(s: Span) -> IResult<Span, Vec<Lang>> {
434 let res = (
435 terminated(tag("typeconstructor"), multispace0),
436 pascal_case_no_space,
437 delimited(
438 terminated(tag("["), multispace0),
439 separated_list0(terminated(tag(","), multispace0), terminated(ltype, multispace0)),
440 terminated(tag("]"), multispace0),
441 ),
442 terminated(alt((tag("recursive"), tag("record"))), multispace0),
443 terminated(tag(";"), multispace0),
444 )
445 .parse(s);
446 match res {
447 Ok((s, (_kw, (name, h), params, category, _semi))) => {
448 let category = match *category.fragment() {
449 "recursive" => ConstructorCategory::Recursive,
450 _ => ConstructorCategory::Record,
451 };
452 Ok((
453 s,
454 vec![Lang::TypeConstructor {
455 name,
456 parameters: params,
457 category,
458 help_data: h,
459 }],
460 ))
461 }
462 Err(r) => Err(r),
463 }
464}
465
466fn single_letter_type_name_exp(s: Span) -> IResult<Span, Vec<Lang>> {
476 let res = (
477 opt(terminated(alt((tag("@export"), tag("@pub"))), multispace0)),
478 terminated(alt((tag("type"), tag("opaque"))), multispace0),
479 single_letter_type_alias,
480 equality_operator,
481 ltype,
482 terminated(tag(";"), multispace0),
483 )
484 .parse(s);
485 match res {
486 Ok((s, (_pub, _kw, Type::Alias(name, params, _, h), _eq, ty, _))) => {
487 push_parse_error(SyntaxError::SingleLetterTypeName {
488 name: name.clone(),
489 help_data: h.clone(),
490 });
491 let h2 = if !params.is_empty() {
492 params[0].clone().into()
493 } else {
494 HelpData::default()
495 };
496 let vari = Var::from_name(&name)
497 .set_type(Type::Params(params.clone(), h2))
498 .to_language();
499 Ok((
500 s,
501 vec![Lang::Alias {
502 identifier: Box::new(vari),
503 parameters: params,
504 target_type: ty,
505 is_public: false,
506 is_export: false,
507 help_data: h,
508 }],
509 ))
510 }
511 Ok((s, (_pub, kw, _, _eq, _ty2, _))) => Ok((s, vec![Lang::Empty(kw.into())])),
512 Err(r) => Err(r),
513 }
514}
515
516fn base_type_exp(s: Span) -> IResult<Span, Lang> {
517 let res = (
518 terminated(tag("type"), multispace0),
519 type_alias,
520 equality_operator,
521 ltype,
522 terminated(tag(";"), multispace0),
523 )
524 .parse(s);
525 match res {
526 Ok((s, (_ty, Type::Alias(name, params, _, h), _eq, ty, _))) => {
527 let h2 = if !params.is_empty() {
528 params[0].clone().into()
529 } else {
530 HelpData::default()
531 };
532 let vari = Var::from_name(&name)
533 .set_type(Type::Params(params.clone(), h2))
534 .to_language();
535 Ok((
536 s,
537 Lang::Alias {
538 identifier: Box::new(vari),
539 parameters: params,
540 target_type: ty,
541 is_public: false,
542 is_export: false,
543 help_data: h,
544 },
545 ))
546 }
547 Ok((s, (_ty, _, _eq, _ty2, _))) => Ok((s, Lang::Empty(_ty.into()))),
548 Err(r) => Err(r),
549 }
550}
551
552fn type_exp(s: Span) -> IResult<Span, Vec<Lang>> {
553 let res = (
554 opt(terminated(alt((tag("@export"), tag("@pub"))), multispace0)),
555 base_type_exp,
556 )
557 .parse(s);
558 match res {
559 Ok((
560 s,
561 (
562 Some(annotation),
563 Lang::Alias {
564 identifier: var,
565 parameters: params,
566 target_type: typ,
567 help_data: h,
568 ..
569 },
570 ),
571 )) => {
572 let is_exp = *annotation.fragment() == "@export";
575 Ok((
576 s,
577 vec![Lang::Alias {
578 identifier: var,
579 parameters: params,
580 target_type: typ,
581 is_public: true,
582 is_export: is_exp,
583 help_data: h,
584 }],
585 ))
586 }
587 Ok((
588 s,
589 (
590 None,
591 Lang::Alias {
592 identifier: var,
593 parameters: params,
594 target_type: typ,
595 help_data: h,
596 ..
597 },
598 ),
599 )) => {
600 let vari = Var::from_language(var.deref().clone()).unwrap().to_language();
601 Ok((
602 s,
603 vec![Lang::Alias {
604 identifier: Box::new(vari),
605 parameters: params,
606 target_type: typ,
607 is_public: false,
608 is_export: false,
609 help_data: h,
610 }],
611 ))
612 }
613 Err(r) => Err(r),
614 _ => todo!(),
615 }
616}
617
618fn type_instead_of_let_exp(s: Span) -> IResult<Span, Vec<Lang>> {
621 let res = (
622 opt(terminated(tag("@pub"), multispace0)),
623 terminated(tag("type"), multispace0),
624 terminated(variable_exp, multispace0),
625 equality_operator,
626 single_parse,
627 )
628 .parse(s);
629 match res {
630 Ok((s, (pub_ann, type_kw, (name, h), _eq, body))) => {
631 push_parse_error(SyntaxError::TypeInsteadOfLet {
632 name: name.clone(),
633 help_data: h.clone(),
634 });
635 let is_pub = pub_ann.is_some();
636 Ok((
637 s,
638 vec![Lang::Let {
639 variable: Box::new(Lang::Variable {
640 name,
641 is_opaque: false,
642 related_type: Type::Empty(HelpData::default()),
643 help_data: h,
644 }),
645 r#type: Type::Empty(type_kw.clone().into()),
646 expression: Box::new(body),
647 is_public: is_pub,
648 is_testable: is_pub,
649 is_export: false,
650 help_data: type_kw.into(),
651 }],
652 ))
653 }
654 Err(r) => Err(r),
655 }
656}
657
658fn base_opaque_exp(s: Span) -> IResult<Span, Lang> {
659 let res = (
660 terminated(tag("opaque"), multispace0),
661 type_alias,
662 equality_operator,
663 ltype,
664 terminated(tag(";"), multispace0),
665 )
666 .parse(s);
667 match res {
668 Ok((s, (_ty, Type::Alias(name, params, _, h), _eq, ty, _))) => {
669 let vari = Var::from_name(&name)
670 .set_type(Type::Params(params.clone(), params.clone().into()))
671 .set_opacity(true)
672 .to_language();
673 Ok((
674 s,
675 Lang::Alias {
676 identifier: Box::new(vari),
677 parameters: params,
678 target_type: ty,
679 is_public: false,
680 is_export: false,
681 help_data: h,
682 },
683 ))
684 }
685 Ok((s, (_ty, _, _eq, _ty2, _))) => Ok((s, Lang::Empty(_ty.into()))),
686 Err(r) => Err(r),
687 }
688}
689
690fn opaque_exp(s: Span) -> IResult<Span, Vec<Lang>> {
691 let res = (
692 opt(terminated(alt((tag("@export"), tag("@pub"))), multispace0)),
693 base_opaque_exp,
694 )
695 .parse(s);
696 match res {
697 Ok((
698 s,
699 (
700 Some(annotation),
701 Lang::Alias {
702 identifier: var,
703 parameters: params,
704 target_type: typ,
705 help_data: h,
706 ..
707 },
708 ),
709 )) => {
710 let is_exp = *annotation.fragment() == "@export";
711 let vari = Var::from_language(var.deref().clone())
712 .unwrap()
713 .set_opacity(true)
714 .to_language();
715 Ok((
716 s,
717 vec![Lang::Alias {
718 identifier: Box::new(vari),
719 parameters: params,
720 target_type: typ,
721 is_public: true,
722 is_export: is_exp,
723 help_data: h,
724 }],
725 ))
726 }
727 Ok((
728 s,
729 (
730 None,
731 Lang::Alias {
732 identifier: var,
733 parameters: params,
734 target_type: typ,
735 help_data: h,
736 ..
737 },
738 ),
739 )) => {
740 let vari = Var::from_language(var.deref().clone())
741 .unwrap()
742 .set_opacity(true)
743 .to_language();
744 Ok((
745 s,
746 vec![Lang::Alias {
747 identifier: Box::new(vari),
748 parameters: params,
749 target_type: typ,
750 is_public: false,
751 is_export: false,
752 help_data: h,
753 }],
754 ))
755 }
756 Err(r) => Err(r),
757 _ => todo!(),
758 }
759}
760
761pub fn module(s: Span) -> IResult<Span, Vec<Lang>> {
762 let res = (
763 terminated(tag("module"), multispace0),
764 terminated(variable_recognizer, multispace0),
765 terminated(tag("{"), multispace0),
766 base_parse,
767 terminated(tag("}"), multispace0),
768 opt(terminated(tag(";"), multispace0)),
769 )
770 .parse(s);
771 match res {
772 Ok((s, (modu, (name, _), _op, v, _cl, _dv))) => Ok((
773 s,
774 vec![Lang::Module {
775 name,
776 body: v,
777 module_position: ModulePosition::Internal,
778 config: Config::default(),
779 help_data: modu.into(),
780 }],
781 )),
782 Err(r) => Err(r),
783 }
784}
785
786fn import_module(s: Span) -> IResult<Span, Vec<Lang>> {
787 let res = (
788 terminated(tag("import"), multispace0),
789 terminated(variable_recognizer, multispace0),
790 opt((
791 terminated(tag("as"), multispace0),
792 terminated(variable_recognizer, multispace0),
793 )),
794 opt(terminated(tag(";"), multispace0)),
795 )
796 .parse(s);
797 match res {
798 Ok((s, (import_kw, (name, _), None, _))) => Ok((
799 s,
800 vec![Lang::ModuleImport {
801 value: name,
802 help_data: import_kw.into(),
803 }],
804 )),
805 Ok((s, (_, (name, h), Some((_, (alias, _))), _))) => {
806 let module_var = Lang::Variable {
807 name,
808 is_opaque: false,
809 related_type: Type::Empty(HelpData::default()),
810 help_data: h.clone(),
811 };
812 let alias_var = Var::from_name(&alias).to_language();
813 Ok((
814 s,
815 vec![Lang::Let {
816 variable: Box::new(alias_var),
817 r#type: Type::Empty(HelpData::default()),
818 expression: Box::new(module_var),
819 is_public: false,
820 is_testable: false,
821 is_export: false,
822 help_data: h,
823 }],
824 ))
825 }
826 Err(r) => Err(r),
827 }
828}
829
830fn import_from_exp(s: Span) -> IResult<Span, Vec<Lang>> {
831 let res = (
832 terminated(tag("@importFrom"), multispace1),
833 terminated(
834 take_while1(|c: char| c.is_alphanumeric() || c == '.' || c == '_'),
835 multispace1,
836 ),
837 many1(terminated(
838 take_while1(|c: char| c.is_alphanumeric() || c == '.' || c == '_'),
839 multispace0,
840 )),
841 opt(terminated(tag(";"), multispace0)),
842 )
843 .parse(s);
844 match res {
845 Ok((s, (kw, pkg, fns, _))) => Ok((
846 s,
847 vec![Lang::ImportFrom {
848 package: pkg.fragment().to_string(),
849 functions: fns.iter().map(|f| f.fragment().to_string()).collect(),
850 help_data: kw.into(),
851 }],
852 )),
853 Err(r) => Err(r),
854 }
855}
856
857fn assign(s: Span) -> IResult<Span, Vec<Lang>> {
858 let res = (
859 variable,
860 alt((terminated(tag("="), multispace0), terminated(tag("<-"), multispace0))),
861 parse_elements,
862 opt(terminated(tag(";"), multispace0)),
863 )
864 .parse(s);
865 match res {
866 Ok((s, ((var, _), _eq, exp, Some(_)))) => Ok((
867 s,
868 vec![Lang::Assign {
869 identifier: Box::new(var.clone()),
870 expression: Box::new(exp),
871 help_data: var.into(),
872 }],
873 )),
874 Ok((s, ((var, _), _eq, exp, None))) => {
875 push_parse_error(SyntaxError::ForgottenSemicolon(exp.clone().into()));
876 let assign = Lang::Assign {
877 identifier: Box::new(var.clone()),
878 expression: Box::new(exp),
879 help_data: var.into(),
880 };
881 Ok((s, vec![assign]))
882 }
883 Err(r) => Err(r),
884 }
885}
886
887fn comment(s: Span) -> IResult<Span, Vec<Lang>> {
888 let res = (tag("#"), not_line_ending, opt(line_ending), multispace0).parse(s);
889 match res {
890 Ok((s, (_hashtag, txt, _, _))) => Ok((
891 s,
892 vec![Lang::Comment {
893 value: txt.to_string(),
894 help_data: _hashtag.into(),
895 }],
896 )),
897 Err(r) => Err(r),
898 }
899}
900
901fn wrong_comment(s: Span) -> IResult<Span, Vec<Lang>> {
912 let res = (tag("//"), not_line_ending, opt(line_ending), multispace0).parse(s);
913 match res {
914 Ok((s, (slashes, txt, _, _))) => {
915 push_parse_error(SyntaxError::WrongCommentSyntax(slashes.clone().into()));
916 Ok((
917 s,
918 vec![Lang::Comment {
919 value: txt.to_string(),
920 help_data: slashes.into(),
921 }],
922 ))
923 }
924 Err(r) => Err(r),
925 }
926}
927
928pub fn simple_exp(s: Span) -> IResult<Span, Vec<Lang>> {
929 let res = (parse_elements, opt(terminated(tag(";"), multispace0))).parse(s);
930 match res {
931 Ok((s, (lang, Some(_)))) => Ok((s, vec![lang])),
932 Ok((s, (lang, None))) => {
933 push_parse_error(SyntaxError::ForgottenSemicolon(lang.clone().into()));
934 Ok((s, vec![lang]))
935 }
936 Err(r) => Err(r),
937 }
938}
939
940fn mod_imp(s: Span) -> IResult<Span, Vec<Lang>> {
941 let res = (
942 terminated(tag("mod"), multispace0),
943 terminated(variable_exp, multispace0),
944 terminated(tag(";"), multispace0),
945 )
946 .parse(s);
947 match res {
948 Ok((s, (_mod, (name, _), _sc))) => Ok((
949 s,
950 vec![Lang::ModuleImport {
951 value: name.to_string(),
952 help_data: _mod.into(),
953 }],
954 )),
955 Err(r) => Err(r),
956 }
957}
958
959fn import_var(s: Span) -> IResult<Span, Vec<Lang>> {
960 let res = (
961 terminated(tag("use"), multispace0),
962 variable,
963 terminated(tag(";"), multispace0),
964 )
965 .parse(s);
966 match res {
967 Ok((s, (_use, (lang, case), _sc))) => {
968 let res = match case {
969 Case::Maj => Var::from_language(lang).unwrap().to_alias_lang(),
970 _ => Var::from_language(lang).unwrap().to_let(),
971 };
972 Ok((s, vec![res]))
973 }
974 Err(r) => Err(r),
975 }
976}
977
978fn import_type(s: Span) -> IResult<Span, Vec<Lang>> {
979 let res = (
980 terminated(tag("use"), multispace0),
981 type_alias,
982 terminated(tag(";"), multispace0),
983 )
984 .parse(s);
985
986 match res {
987 Ok((s, (_use, alias, _sc))) => Ok((
988 s,
989 vec![Lang::Import {
990 value: alias,
991 help_data: _use.into(),
992 }],
993 )),
994 Err(r) => Err(r),
995 }
996}
997
998fn tests(s: Span) -> IResult<Span, Vec<Lang>> {
999 let res = (tag("Test"), delimited(tag("["), base_parse, tag("]"))).parse(s);
1000 match res {
1001 Ok((s, (_t, body))) => Ok((
1002 s,
1003 vec![Lang::Test {
1004 value: body,
1005 help_data: _t.into(),
1006 }],
1007 )),
1008 Err(r) => Err(r),
1009 }
1010}
1011
1012fn library(s: Span) -> IResult<Span, Vec<Lang>> {
1013 let res = (tag("library("), variable_exp, tag(")"), opt(tag(";")), multispace0).parse(s);
1014
1015 match res {
1016 Ok((s, (_lib, (var, h), _cl, Some(_col), _))) => Ok((
1017 s,
1018 vec![Lang::Library {
1019 value: var,
1020 help_data: h.clone(),
1021 }],
1022 )),
1023 Ok((_, (_lib, _var, _cl, None, _))) => {
1024 panic!("You forgot to put a ';' at the end of the line")
1025 }
1026 Err(r) => Err(r),
1027 }
1028}
1029
1030fn use_item_exp(s: Span) -> IResult<Span, crate::components::language::use_lang::UseItem> {
1031 use crate::components::language::use_lang::UseItem;
1032 let res = (
1034 terminated(variable_recognizer, multispace0),
1035 opt(preceded(
1036 pair(tag("as"), multispace0),
1037 terminated(variable_recognizer, multispace0),
1038 )),
1039 )
1040 .parse(s);
1041 match res {
1042 Ok((s, ((name, _), alias_opt))) => {
1043 let alias = alias_opt.map(|(alias_name, _)| alias_name);
1044 Ok((s, UseItem { name, alias }))
1045 }
1046 Err(r) => Err(r),
1047 }
1048}
1049
1050fn use_items_selector(s: Span) -> IResult<Span, crate::components::language::use_lang::UseSelector> {
1051 use crate::components::language::use_lang::UseSelector;
1052 let res = (
1053 pair(tag("{"), multispace0),
1054 separated_list0(pair(tag(","), multispace0), use_item_exp),
1055 opt(pair(tag(","), multispace0)),
1056 pair(tag("}"), multispace0),
1057 )
1058 .parse(s);
1059 match res {
1060 Ok((s, (_, items, _, _))) => Ok((s, UseSelector::Items(items))),
1061 Err(r) => Err(r),
1062 }
1063}
1064
1065fn use_selector_exp(s: Span) -> IResult<Span, crate::components::language::use_lang::UseSelector> {
1066 use crate::components::language::use_lang::UseSelector;
1067 alt((
1068 map(terminated(tag("*"), multispace0), |_| UseSelector::Wildcard),
1069 use_items_selector,
1070 ))
1071 .parse(s)
1072}
1073
1074fn use_module_directive(s: Span) -> IResult<Span, Vec<Lang>> {
1075 use crate::components::language::use_lang::UseSelector;
1076
1077 let res = (
1079 terminated(tag("use"), multispace0),
1080 terminated(variable_recognizer, multispace0),
1081 pair(tag("::"), multispace0),
1082 )
1083 .parse(s);
1084
1085 let (s, (use_kw, (first_seg, _), _)) = res?;
1086
1087 let mut path = vec![first_seg];
1088 let mut current_s = s;
1089 let selector;
1090
1091 loop {
1092 match use_selector_exp(current_s.clone()) {
1093 Ok((s2, sel)) => {
1094 selector = sel;
1095 current_s = s2;
1096 break;
1097 }
1098 Err(_) => match terminated(variable_recognizer, multispace0).parse(current_s.clone()) {
1099 Ok((s2, (seg, _))) => {
1100 let colon_res: IResult<Span, (Span, Span)> = pair(tag("::"), multispace0).parse(s2.clone());
1101 match colon_res {
1102 Ok((s3, _)) => {
1103 path.push(seg);
1104 current_s = s3;
1105 }
1106 Err(_) => {
1107 use crate::components::language::use_lang::UseItem;
1108 selector = UseSelector::Items(vec![UseItem { name: seg, alias: None }]);
1109 current_s = s2;
1110 break;
1111 }
1112 }
1113 }
1114 Err(e) => return Err(e),
1115 },
1116 }
1117 }
1118
1119 let res = terminated(tag(";"), multispace0).parse(current_s);
1120 let (s, _) = res?;
1121
1122 Ok((
1123 s,
1124 vec![Lang::UseModule {
1125 module_path: path,
1126 selector,
1127 help_data: use_kw.into(),
1128 }],
1129 ))
1130}
1131
1132fn use_exp(s: Span) -> IResult<Span, Vec<Lang>> {
1133 let res = (
1134 tag("use("),
1135 chars,
1136 tag(", "),
1137 alt((vector, chars)),
1138 terminated(tag(");"), multispace0),
1139 )
1140 .parse(s);
1141 match res {
1142 Ok((s, (us, lib, _, members, _))) => Ok((
1143 s,
1144 vec![Lang::Use {
1145 lang: Box::new(lib),
1146 members: Box::new(members),
1147 help_data: us.into(),
1148 }],
1149 )),
1150 Err(r) => Err(r),
1151 }
1152}
1153
1154fn custom_operators(s: Span) -> IResult<Span, (String, HelpData)> {
1155 let res = custom_op.parse(s);
1156 match res {
1157 Ok((s, co)) => Ok((s, (co.clone().to_string(), co.into()))),
1158 Err(r) => Err(r),
1159 }
1160}
1161
1162fn return_stmt(s: Span) -> IResult<Span, Vec<Lang>> {
1163 let (s, e) = return_exp(s)?;
1164 Ok((s, vec![e]))
1165}
1166
1167fn stmt_exp(s: Span) -> IResult<Span, Vec<Lang>> {
1168 let res = (parse_elements, terminated(tag(";"), multispace0)).parse(s);
1169 match res {
1170 Ok((s, (lang, _))) => Ok((s, vec![lang])),
1171 Err(r) => Err(r),
1172 }
1173}
1174
1175fn head_lang(lang: &Lang) -> Option<Lang> {
1176 match lang {
1177 Lang::Variable { .. } => Some(lang.clone()),
1178 Lang::Operator {
1179 operator: Op::Pipe(_) | Op::Dot(_),
1180 rhs,
1181 ..
1182 } => head_lang(rhs),
1183 _ => None,
1184 }
1185}
1186
1187fn implicit_mutate(s: Span) -> IResult<Span, Vec<Lang>> {
1188 let res = (parse_elements, terminated(tag("!;"), multispace0)).parse(s);
1189 match res {
1190 Ok((s, (expr, excl))) => match head_lang(&expr) {
1191 Some(lhs) => Ok((
1192 s,
1193 vec![Lang::Assign {
1194 identifier: Box::new(lhs),
1195 expression: Box::new(expr),
1196 help_data: excl.into(),
1197 }],
1198 )),
1199 None => {
1200 push_parse_error(SyntaxError::MutationTargetNotAssignable(expr.clone().into()));
1201 Err(nom::Err::Error(nom::error::Error::new(s, nom::error::ErrorKind::Tag)))
1202 }
1203 },
1204 Err(r) => Err(r),
1205 }
1206}
1207
1208fn signature_variable(s: Span) -> IResult<Span, Vec<Lang>> {
1209 let res = (
1210 tag("@"),
1211 alt((variable_recognizer, custom_operators)),
1212 terminated(tag(":"), multispace0),
1213 ltype,
1214 terminated(tag(";"), multispace0),
1215 )
1216 .parse(s);
1217 match res {
1218 Ok((s, (at, (name, h), _col, typ, _))) => {
1219 let var2 = Var::from_name(&name).set_help_data(h).set_type(typ.clone());
1220 Ok((
1221 s,
1222 vec![Lang::Signature {
1223 identifier: var2,
1224 target_type: typ,
1225 help_data: at.into(),
1226 is_extern: false,
1227 extern_r_name: None,
1228 }],
1229 ))
1230 }
1231 Err(r) => Err(r),
1232 }
1233}
1234
1235fn signature_opaque(s: Span) -> IResult<Span, Vec<Lang>> {
1236 let res = (
1237 tag("@"),
1238 type_alias,
1239 terminated(tag(":"), multispace0),
1240 ltype,
1241 terminated(tag(";"), multispace0),
1242 )
1243 .parse(s);
1244 match res {
1245 Ok((s, (at, Type::Alias(name, _params, _, h), _, typ, _))) => {
1246 let var2 = Var::from_name(&name).set_help_data(h.clone()).set_type(typ.clone());
1247 Ok((
1248 s,
1249 vec![Lang::Signature {
1250 identifier: var2,
1251 target_type: typ,
1252 help_data: at.into(),
1253 is_extern: false,
1254 extern_r_name: None,
1255 }],
1256 ))
1257 }
1258 Ok((_s, (_, _, _, _, _))) => todo!(),
1259 Err(r) => Err(r),
1260 }
1261}
1262
1263fn signature_extern(s: Span) -> IResult<Span, Vec<Lang>> {
1264 let res = (
1265 tag("@extern"),
1266 multispace1,
1267 opt((
1268 take_while1(|c: char| c.is_alphanumeric() || c == '_' || c == '.'),
1269 tag("::"),
1270 )),
1271 alt((variable_recognizer, custom_operators)),
1272 terminated(tag(":"), multispace0),
1273 ltype,
1274 terminated(tag(";"), multispace0),
1275 )
1276 .parse(s);
1277 match res {
1278 Ok((s, (at, _, pkg_prefix, (name, h), _col, typ, _))) => {
1279 let r_name = pkg_prefix.map(|(pkg, _)| format!("{}::{}", pkg, name));
1280 let var2 = Var::from_name(&name).set_help_data(h).set_type(typ.clone());
1281 Ok((
1282 s,
1283 vec![Lang::Signature {
1284 identifier: var2,
1285 target_type: typ,
1286 help_data: at.into(),
1287 is_extern: true,
1288 extern_r_name: r_name,
1289 }],
1290 ))
1291 }
1292 Err(r) => Err(r),
1293 }
1294}
1295
1296pub fn signature(s: Span) -> IResult<Span, Vec<Lang>> {
1297 alt((signature_extern, signature_opaque, signature_variable)).parse(s)
1298}
1299
1300fn for_loop(s: Span) -> IResult<Span, Vec<Lang>> {
1301 let res = (
1302 terminated(tag("for"), multispace0),
1303 terminated(tag("("), multispace0),
1304 terminated(variable_exp, multispace0),
1305 terminated(tag("in"), multispace0),
1306 terminated(single_element, multispace0),
1307 terminated(tag(")"), multispace0),
1308 scope,
1309 terminated(tag(";"), multispace0),
1310 )
1311 .parse(s);
1312 match res {
1313 Ok((s, (_for, _op, (var_str, _h), _in, iterator, _cl, scop, _semi))) => Ok((
1314 s,
1315 vec![Lang::ForLoop {
1316 identifier: Var::from_name(&var_str),
1317 expression: Box::new(iterator),
1318 body: Box::new(scop),
1319 help_data: _for.into(),
1320 }],
1321 )),
1322 Err(r) => Err(r),
1323 }
1324}
1325
1326fn while_loop(s: Span) -> IResult<Span, Vec<Lang>> {
1327 let res = (
1328 terminated(tag("while"), multispace0),
1329 terminated(tag("("), multispace0),
1330 terminated(single_element, multispace0),
1331 terminated(tag(")"), multispace0),
1332 scope,
1333 terminated(tag(";"), multispace0),
1334 )
1335 .parse(s);
1336 match res {
1337 Ok((s, (_while, _op, condition, _cl, scop, _semi))) => Ok((
1338 s,
1339 vec![Lang::WhileLoop {
1340 condition: Box::new(condition),
1341 body: Box::new(scop),
1342 help_data: _while.into(),
1343 }],
1344 )),
1345 Err(r) => Err(r),
1346 }
1347}
1348
1349fn loop_loop(s: Span) -> IResult<Span, Vec<Lang>> {
1350 let res = (
1351 terminated(tag("loop"), multispace0),
1352 scope,
1353 terminated(tag(";"), multispace0),
1354 )
1355 .parse(s);
1356 match res {
1357 Ok((s, (_loop, scop, _semi))) => Ok((
1358 s,
1359 vec![Lang::Loop {
1360 body: Box::new(scop),
1361 help_data: _loop.into(),
1362 }],
1363 )),
1364 Err(r) => Err(r),
1365 }
1366}
1367
1368fn test_block(s: Span) -> IResult<Span, Vec<Lang>> {
1369 let res = (terminated(tag("Test"), multispace0), scope).parse(s);
1370 match res {
1373 Ok((s, (tst, body))) => Ok((
1374 s,
1375 vec![Lang::TestBlock {
1376 value: Box::new(body),
1377 help_data: tst.into(),
1378 }],
1379 )),
1380 Err(r) => Err(r),
1381 }
1382}
1383
1384pub fn base_parse(s: Span) -> IResult<Span, Vec<Lang>> {
1386 let res = (
1387 opt(multispace0),
1388 many0(alt((
1389 alt((
1390 library,
1391 break_exp,
1392 next_exp,
1393 use_exp,
1394 test_block,
1395 while_loop,
1396 loop_loop,
1397 for_loop,
1398 import_from_exp,
1399 signature,
1400 tests,
1401 import_module,
1402 use_module_directive,
1403 import_type,
1404 )),
1405 alt((
1406 import_var,
1407 mod_imp,
1408 comment,
1409 wrong_comment,
1410 typeconstructor_exp,
1411 single_letter_type_name_exp,
1412 type_exp,
1413 type_instead_of_let_exp,
1414 opaque_exp,
1415 let_tuple_exp,
1416 let_exp,
1417 module,
1418 assign,
1419 return_stmt,
1420 implicit_mutate,
1421 stmt_exp,
1422 )),
1423 ))),
1424 opt(parse_elements),
1425 )
1426 .parse(s);
1427 match res {
1428 Ok((s, (_, v, None))) if v.is_empty() => Ok((s, vec![])),
1430 Ok((s, (_, v, Some(expr)))) if v.is_empty() => Ok((s, vec![expr])),
1432 Ok((s, (_, v, trailing))) => {
1434 let mut result: Vec<Lang> = v.into_iter().flatten().collect();
1435 if let Some(expr) = trailing {
1436 result.push(expr);
1437 }
1438 Ok((s, result))
1439 }
1440 Err(r) => Err(r),
1441 }
1442}
1443
1444pub fn parse(s: Span) -> ParseResult {
1449 let res = base_parse(s.clone());
1450 match res {
1451 Ok((remaining, v)) => {
1452 if !remaining.fragment().is_empty() {
1453 let element = remaining.fragment().lines().next().unwrap_or("").trim().to_string();
1454 let line = remaining.location_line();
1455 let help_data = HelpData::from(remaining);
1456 push_parse_error(SyntaxError::UnknownElement {
1457 element,
1458 line,
1459 help_data,
1460 });
1461 }
1462 ParseResult::new(Lang::Lines {
1463 value: v.clone(),
1464 help_data: v.into(),
1465 })
1466 }
1467 Err(_) => panic!("Can't parse string {}", s),
1468 }
1469}
1470
1471pub fn parse_legacy(s: Span) -> Lang {
1476 parse(s).ast
1477}
1478
1479pub fn parse2(s: Span) -> Result<Lang, String> {
1480 let res = base_parse(s.clone());
1481 let _ = take_parse_errors();
1483 match res {
1484 Ok((_, v)) => Ok(v[0].clone()),
1485 Err(_) => Err(format!("Can't parse string {}", s)),
1486 }
1487}
1488
1489pub fn parse_from_string(source: &str, filename: &str) -> Lang {
1494 use crate::components::error_message::help_data::register_source;
1495
1496 register_source(filename, source);
1498
1499 let span: Span = LocatedSpan::new_extra(source, filename.to_string());
1501
1502 parse(span).ast
1504}
1505
1506pub fn parse_from_string_with_errors(source: &str, filename: &str) -> ParseResult {
1508 use crate::components::error_message::help_data::register_source;
1509
1510 register_source(filename, source);
1512
1513 let span: Span = LocatedSpan::new_extra(source, filename.to_string());
1515
1516 parse(span)
1518}
1519
1520#[cfg(test)]
1522mod tesus {
1523 use super::*;
1524
1525 #[test]
1526 fn test_semicolon1() {
1527 let res = parse("let a <- 5".into());
1528 assert!(res.has_errors(), "Missing semicolon should produce a syntax error");
1530 assert_eq!(res.errors.len(), 1, "Should have exactly one error");
1531 match &res.errors[0] {
1532 SyntaxError::ForgottenSemicolon(_) => (),
1533 _ => panic!("Expected ForgottenSemicolon error"),
1534 }
1535 }
1536
1537 #[test]
1538 fn test_semicolon_standalone_exp() {
1539 let res = parse("f(x)".into());
1540 assert!(
1542 !res.has_errors(),
1543 "A standalone expression without semicolon is valid (case 2)"
1544 );
1545 }
1546
1547 #[test]
1548 fn test_semicolon_assign() {
1549 let res = parse("a <- 12".into());
1550 assert!(
1551 res.has_errors(),
1552 "An assign expression without semicolon should produce a syntax error"
1553 );
1554 match &res.errors[0] {
1555 SyntaxError::ForgottenSemicolon(_) => (),
1556 _ => panic!("Expected ForgottenSemicolon error"),
1557 }
1558 }
1559
1560 #[test]
1561 fn test_assign1() {
1562 let res = assign("a <- 12;".into()).unwrap().1;
1563 assert_eq!(
1564 "Assign",
1565 res[0].simple_print(),
1566 "The expression 'a <- 12;' should be identified as an assignation"
1567 );
1568 }
1569
1570 #[test]
1573 fn test_let_instead_of_type() {
1574 let res = parse("let MyType <- int;".into());
1575 assert!(res.has_errors(), "let with PascalCase should produce a syntax error");
1576 assert_eq!(res.errors.len(), 1, "Should have exactly one error");
1577 match &res.errors[0] {
1578 SyntaxError::LetInsteadOfType { name, .. } => {
1579 assert_eq!(name, "MyType", "Error should reference the type name");
1580 }
1581 _ => panic!("Expected LetInsteadOfType error"),
1582 }
1583 }
1584
1585 #[test]
1586 fn test_let_instead_of_type_with_pub() {
1587 let res = parse("@pub let MyAlias <- num;".into());
1588 assert!(
1589 res.has_errors(),
1590 "@pub let with PascalCase should produce a syntax error"
1591 );
1592 assert!(res
1593 .errors
1594 .iter()
1595 .any(|e| matches!(e, SyntaxError::LetInsteadOfType { .. })));
1596 }
1597
1598 #[test]
1599 fn test_let_with_lowercase_is_fine() {
1600 let res = parse("let my_var <- 42;".into());
1601 assert!(
1602 !res.has_errors(),
1603 "let with snake_case should not produce a syntax error"
1604 );
1605 }
1606
1607 #[test]
1608 fn test_type_instead_of_let() {
1609 let res = parse("type my_var <- 42;".into());
1610 assert!(res.has_errors(), "type with snake_case should produce a syntax error");
1611 assert_eq!(res.errors.len(), 1, "Should have exactly one error");
1612 match &res.errors[0] {
1613 SyntaxError::TypeInsteadOfLet { name, .. } => {
1614 assert_eq!(name, "my_var", "Error should reference the variable name");
1615 }
1616 _ => panic!("Expected TypeInsteadOfLet error"),
1617 }
1618 }
1619
1620 #[test]
1621 fn test_type_instead_of_let_with_pub() {
1622 let res = parse("@pub type my_binding <- num;".into());
1623 assert!(
1624 res.has_errors(),
1625 "@pub type with snake_case should produce a syntax error"
1626 );
1627 assert!(res
1628 .errors
1629 .iter()
1630 .any(|e| matches!(e, SyntaxError::TypeInsteadOfLet { .. })));
1631 }
1632
1633 #[test]
1634 fn test_type_with_pascalcase_is_fine() {
1635 let res = parse("type MyAlias <- int;".into());
1636 assert!(
1637 !res.has_errors(),
1638 "type with PascalCase should not produce a syntax error"
1639 );
1640 }
1641
1642 #[test]
1645 fn test_single_letter_type_name_is_an_error() {
1646 let res = parse("type A <- int;".into());
1647 assert!(
1648 res.has_errors(),
1649 "single uppercase letter alias name should produce a syntax error"
1650 );
1651 match &res.errors[0] {
1652 SyntaxError::SingleLetterTypeName { name, .. } => {
1653 assert_eq!(name, "A");
1654 }
1655 other => panic!("Expected SingleLetterTypeName error, got {:?}", other),
1656 }
1657 match &res.ast {
1660 Lang::Lines { value, .. } => {
1661 assert_eq!(value.len(), 1);
1662 assert!(matches!(value[0], Lang::Alias { .. }));
1663 }
1664 other => panic!("Expected Lang::Lines, got {:?}", other),
1665 }
1666 }
1667
1668 #[test]
1669 fn test_single_letter_opaque_name_is_an_error() {
1670 let res = parse("opaque Z <- num;".into());
1671 assert!(
1672 res.has_errors(),
1673 "single uppercase letter opaque name should produce a syntax error"
1674 );
1675 match &res.errors[0] {
1676 SyntaxError::SingleLetterTypeName { name, .. } => {
1677 assert_eq!(name, "Z");
1678 }
1679 other => panic!("Expected SingleLetterTypeName error, got {:?}", other),
1680 }
1681 }
1682
1683 #[test]
1684 fn test_single_letter_type_name_with_pub() {
1685 let res = parse("@pub type T <- int;".into());
1686 assert!(
1687 res.has_errors(),
1688 "@pub single-letter alias name should still produce a syntax error"
1689 );
1690 assert!(res
1691 .errors
1692 .iter()
1693 .any(|e| matches!(e, SyntaxError::SingleLetterTypeName { .. })));
1694 }
1695
1696 #[test]
1697 fn test_two_letter_type_name_is_fine() {
1698 let res = parse("type Ab <- int;".into());
1699 assert!(
1700 !res.has_errors(),
1701 "a two-letter alias name should not produce a syntax error"
1702 );
1703 }
1704
1705 fn extract_let_expression(ast: &Lang) -> &Lang {
1708 match ast {
1709 Lang::Lines { value, .. } => match &value[0] {
1710 Lang::Let { expression, .. } => expression,
1711 other => panic!("Expected Lang::Let, got {:?}", other),
1712 },
1713 other => panic!("Expected Lang::Lines, got {:?}", other),
1714 }
1715 }
1716
1717 #[test]
1718 fn test_list_brace_positional_is_an_error() {
1719 let res = parse("let x <- list{1, 2, 3};".into());
1720 assert!(
1721 res.has_errors(),
1722 "list{{...}} with positional elements should produce a syntax error"
1723 );
1724 match &res.errors[0] {
1725 SyntaxError::KeywordRecordPositionalElements { keyword, .. } => {
1726 assert_eq!(keyword, "list");
1727 }
1728 other => panic!("Expected KeywordRecordPositionalElements error, got {:?}", other),
1729 }
1730 match extract_let_expression(&res.ast) {
1732 Lang::Tuple { value, .. } => assert_eq!(value.len(), 3),
1733 other => panic!("Expected Lang::Tuple, got {:?}", other),
1734 }
1735 }
1736
1737 #[test]
1738 fn test_record_brace_positional_is_an_error() {
1739 let res = parse("let x <- record{1, 2, 3};".into());
1740 assert!(
1741 res.has_errors(),
1742 "record{{...}} with positional elements should produce a syntax error"
1743 );
1744 match &res.errors[0] {
1745 SyntaxError::KeywordRecordPositionalElements { keyword, .. } => {
1746 assert_eq!(keyword, "record");
1747 }
1748 other => panic!("Expected KeywordRecordPositionalElements error, got {:?}", other),
1749 }
1750 match extract_let_expression(&res.ast) {
1751 Lang::Tuple { value, .. } => assert_eq!(value.len(), 3),
1752 other => panic!("Expected Lang::Tuple, got {:?}", other),
1753 }
1754 }
1755
1756 #[test]
1757 fn test_object_brace_positional_is_an_error() {
1758 let res = parse("let x <- object{1, 2, 3};".into());
1759 assert!(
1760 res.has_errors(),
1761 "object{{...}} with positional elements should produce a syntax error"
1762 );
1763 match &res.errors[0] {
1764 SyntaxError::KeywordRecordPositionalElements { keyword, .. } => {
1765 assert_eq!(keyword, "object");
1766 }
1767 other => panic!("Expected KeywordRecordPositionalElements error, got {:?}", other),
1768 }
1769 match extract_let_expression(&res.ast) {
1770 Lang::Tuple { value, .. } => assert_eq!(value.len(), 3),
1771 other => panic!("Expected Lang::Tuple, got {:?}", other),
1772 }
1773 }
1774
1775 #[test]
1776 fn test_list_brace_named_fields_still_fine() {
1777 let res = parse("let x <- list{ a = 1, b = 2 };".into());
1778 assert!(
1779 !res.has_errors(),
1780 "list{{...}} with named fields should keep working (real record literal)"
1781 );
1782 match extract_let_expression(&res.ast) {
1783 Lang::List { value, .. } => assert_eq!(value.len(), 2),
1784 other => panic!("Expected Lang::List, got {:?}", other),
1785 }
1786 }
1787
1788 #[test]
1789 fn test_list_paren_positional_still_fine() {
1790 let res = parse("let x <- list(1, 2, 3);".into());
1793 assert!(
1794 !res.has_errors(),
1795 "list(...) with positional elements should keep working"
1796 );
1797 match extract_let_expression(&res.ast) {
1798 Lang::Tuple { value, .. } => assert_eq!(value.len(), 3),
1799 other => panic!("Expected Lang::Tuple, got {:?}", other),
1800 }
1801 }
1802
1803 #[test]
1804 fn test_colon_brace_positional_still_fine() {
1805 let res = parse("let x <- :{1, 2, 3};".into());
1808 assert!(
1809 !res.has_errors(),
1810 ":{{...}} with positional elements should keep working"
1811 );
1812 match extract_let_expression(&res.ast) {
1813 Lang::Tuple { value, .. } => assert_eq!(value.len(), 3),
1814 other => panic!("Expected Lang::Tuple, got {:?}", other),
1815 }
1816 }
1817
1818 #[test]
1821 fn test_single_equals_in_if_condition_recovers_as_eq() {
1822 let res = parse("if (a = b) { 1 } else { 0 };".into());
1823 assert!(
1824 res.has_errors(),
1825 "a bare `=` in expression position should produce a syntax warning"
1826 );
1827 match &res.errors[0] {
1828 SyntaxError::SingleEqualsComparison(_) => (),
1829 other => panic!("Expected SingleEqualsComparison error, got {:?}", other),
1830 }
1831 match &res.ast {
1833 Lang::Lines { value, .. } => match &value[0] {
1834 Lang::If { condition, .. } => match condition.as_ref() {
1835 Lang::Operator { operator, .. } => {
1836 assert!(matches!(operator, Op::Eq(_)));
1837 }
1838 other => panic!("Expected Lang::Operator, got {:?}", other),
1839 },
1840 other => panic!("Expected Lang::If, got {:?}", other),
1841 },
1842 other => panic!("Expected Lang::Lines, got {:?}", other),
1843 }
1844 }
1845
1846 #[test]
1847 fn test_double_equals_in_if_condition_no_warning() {
1848 let res = parse("if (a == b) { 1 } else { 0 };".into());
1851 assert!(
1852 !res.has_errors(),
1853 "a real `==` comparison should not produce any syntax error"
1854 );
1855 }
1856
1857 #[test]
1858 fn test_match_arrow_not_affected_by_equals_recovery() {
1859 let res = parse("let x <- 5; match x { _ => 1 };".into());
1862 assert!(
1863 !res.has_errors(),
1864 "match arm `=>` should not trigger SingleEqualsComparison"
1865 );
1866 }
1867
1868 #[test]
1869 fn test_default_param_equals_not_affected_by_equals_recovery() {
1870 let res = parse("let greet <- fn(name: char, greeting: char = \"Hello\"): char { greeting };".into());
1876 assert!(
1877 !res.has_errors(),
1878 "default parameter `=` should not trigger SingleEqualsComparison"
1879 );
1880 }
1881
1882 #[test]
1885 fn test_let_tuple_basic() {
1886 let res = let_tuple_exp("let :{a, b, c} <- :{1, 2, 3};".into()).unwrap().1;
1887 assert_eq!(res.len(), 4, "Should produce 4 Let statements (1 tmp + 3 bindings)");
1889 for item in &res {
1890 assert!(
1891 item.simple_print().starts_with("let"),
1892 "Each item should be a Let, got: {}",
1893 item.simple_print()
1894 );
1895 }
1896 }
1897
1898 #[test]
1899 fn test_let_tuple_tmp_variable() {
1900 let res = let_tuple_exp("let :{a, b} <- :{1, 2};".into()).unwrap().1;
1901 if let Lang::Let { variable: var, .. } = &res[0] {
1903 if let Lang::Variable { name, .. } = var.as_ref() {
1904 assert_eq!(name, "__tuple_tmp__");
1905 } else {
1906 panic!("Expected Variable in first Let");
1907 }
1908 } else {
1909 panic!("Expected Let");
1910 }
1911 }
1912
1913 #[test]
1914 fn test_let_tuple_bindings() {
1915 let res = let_tuple_exp("let :{x, y} <- :{10, 20};".into()).unwrap().1;
1916 if let Lang::Let {
1918 variable: var,
1919 expression: body,
1920 ..
1921 } = &res[1]
1922 {
1923 if let Lang::Variable { name, .. } = var.as_ref() {
1924 assert_eq!(name, "x");
1925 } else {
1926 panic!("Expected Variable 'x'");
1927 }
1928 assert_eq!(body.simple_print(), "Operator", "Body should be a Dot operator");
1929 } else {
1930 panic!("Expected Let");
1931 }
1932 if let Lang::Let { variable: var, .. } = &res[2] {
1934 if let Lang::Variable { name, .. } = var.as_ref() {
1935 assert_eq!(name, "y");
1936 } else {
1937 panic!("Expected Variable 'y'");
1938 }
1939 } else {
1940 panic!("Expected Let");
1941 }
1942 }
1943
1944 #[test]
1945 fn test_let_tuple_wildcard() {
1946 let res = let_tuple_exp("let :{a, _, c} <- :{1, 2, 3};".into()).unwrap().1;
1947 assert_eq!(res.len(), 3, "Should produce 3 Let statements (wildcard skipped)");
1949 if let Lang::Let { variable: var, .. } = &res[1] {
1951 if let Lang::Variable { name, .. } = var.as_ref() {
1952 assert_eq!(name, "a");
1953 } else {
1954 panic!("Expected Variable 'a'");
1955 }
1956 } else {
1957 panic!("Expected Let");
1958 }
1959 if let Lang::Let { variable: var, .. } = &res[2] {
1961 if let Lang::Variable { name, .. } = var.as_ref() {
1962 assert_eq!(name, "c");
1963 } else {
1964 panic!("Expected Variable 'c'");
1965 }
1966 } else {
1967 panic!("Expected Let");
1968 }
1969 }
1970
1971 #[test]
1972 fn test_let_tuple_under_binding_is_arity_error() {
1973 let _ = take_parse_errors();
1974 let _ = let_tuple_exp("let :{a, b} <- :{1, 2, 3};".into()).unwrap().1;
1975 let errors = take_parse_errors();
1976 assert_eq!(errors.len(), 1, "under-binding must raise exactly one error");
1977 match &errors[0] {
1978 SyntaxError::TupleDestructureArityMismatch { expected, found, .. } => {
1979 assert_eq!(*expected, 2);
1980 assert_eq!(*found, 3);
1981 }
1982 other => panic!("Expected TupleDestructureArityMismatch, got {:?}", other),
1983 }
1984 }
1985
1986 #[test]
1987 fn test_let_tuple_over_binding_is_arity_error() {
1988 let _ = take_parse_errors();
1989 let _ = let_tuple_exp("let :{a, b, c, d} <- :{1, 2, 3};".into()).unwrap().1;
1990 let errors = take_parse_errors();
1991 assert_eq!(errors.len(), 1, "over-binding must raise exactly one error");
1992 match &errors[0] {
1993 SyntaxError::TupleDestructureArityMismatch { expected, found, .. } => {
1994 assert_eq!(*expected, 4);
1995 assert_eq!(*found, 3);
1996 }
1997 other => panic!("Expected TupleDestructureArityMismatch, got {:?}", other),
1998 }
1999 }
2000
2001 #[test]
2002 fn test_let_tuple_matching_arity_no_error() {
2003 let _ = take_parse_errors();
2004 let _ = let_tuple_exp("let :{a, b, c} <- :{1, 2, 3};".into()).unwrap().1;
2005 let errors = take_parse_errors();
2006 assert!(errors.is_empty(), "matching arity must not raise an error");
2007 }
2008
2009 #[test]
2010 fn test_let_tuple_wildcard_counts_toward_arity() {
2011 let _ = take_parse_errors();
2012 let _ = let_tuple_exp("let :{a, _} <- :{1, 2, 3};".into()).unwrap().1;
2013 let errors = take_parse_errors();
2014 assert_eq!(
2015 errors.len(),
2016 1,
2017 "`_` still occupies a slot, so this is a 2-vs-3 mismatch"
2018 );
2019 }
2020
2021 #[test]
2022 fn test_let_tuple_dynamic_source_no_arity_check() {
2023 let _ = take_parse_errors();
2026 let _ = let_tuple_exp("let :{a, b} <- get_pair();".into()).unwrap().1;
2027 let errors = take_parse_errors();
2028 assert!(
2029 errors.is_empty(),
2030 "dynamic (non-literal) tuple source must not be flagged at parse time"
2031 );
2032 }
2033
2034 #[test]
2035 fn test_let_tuple_arity_mismatch_full_parse_has_errors() {
2036 let res = parse("let :{a, b} <- :{1, 2, 3};".into());
2037 assert!(
2038 res.has_errors(),
2039 "arity mismatch should surface through the full parse() entry point"
2040 );
2041 }
2042
2043 #[test]
2044 fn test_let_tuple_in_full_parse() {
2045 let res = parse("let :{a, b, c} <- :{1, 2, 3};".into());
2046 assert!(!res.has_errors(), "Let tuple destructuring should parse without errors");
2047 }
2048
2049 #[test]
2050 fn test_let_tuple_with_equals() {
2051 let res = let_tuple_exp("let :{a, b} = :{1, 2};".into()).unwrap().1;
2052 assert_eq!(res.len(), 3, "Should work with '=' operator too");
2053 }
2054
2055 #[test]
2056 fn test_let_tuple_type_check() {
2057 use crate::components::context::Context;
2058 use crate::processes::type_checking::typing;
2059 use crate::utils::builder;
2060
2061 let ast = parse("let :{a, b, c} <- :{1, 2, 3};".into()).ast;
2062 let context = Context::empty();
2063 let tc = typing(&context, &ast);
2064
2065 let ty_a = tc
2067 .context
2068 .get_type_from_existing_variable(crate::components::language::var::Var::from_name("a"));
2069 let ty_b = tc
2070 .context
2071 .get_type_from_existing_variable(crate::components::language::var::Var::from_name("b"));
2072 let ty_c = tc
2073 .context
2074 .get_type_from_existing_variable(crate::components::language::var::Var::from_name("c"));
2075
2076 assert_eq!(ty_a, builder::integer_type(1), "Variable 'a' should be Integer(1)");
2077 assert_eq!(ty_b, builder::integer_type(2), "Variable 'b' should be Integer(2)");
2078 assert_eq!(ty_c, builder::integer_type(3), "Variable 'c' should be Integer(3)");
2079 }
2080
2081 #[test]
2082 fn test_let_tuple_type_check_mixed_types() {
2083 use crate::components::context::Context;
2084 use crate::processes::type_checking::typing;
2085 use crate::utils::builder;
2086
2087 let ast = parse("let :{x, y} <- :{1, 'hello'};".into()).ast;
2088 let context = Context::empty();
2089 let tc = typing(&context, &ast);
2090
2091 let ty_x = tc
2092 .context
2093 .get_type_from_existing_variable(crate::components::language::var::Var::from_name("x"));
2094 let ty_y = tc
2095 .context
2096 .get_type_from_existing_variable(crate::components::language::var::Var::from_name("y"));
2097
2098 assert_eq!(ty_x, builder::integer_type(1), "Variable 'x' should be Integer(1)");
2099 assert_eq!(
2100 ty_y,
2101 builder::character_type("hello"),
2102 "Variable 'y' should be Character('hello')"
2103 );
2104 }
2105
2106 #[test]
2107 fn test_fn_function_type_syntax_error() {
2108 let res = parse("let f: fn(a: int) -> int <- fn(x: int): int { x };".into());
2109 assert!(
2110 res.has_errors(),
2111 "Using 'fn(...)' in type position should produce a syntax error"
2112 );
2113 let fn_type_error = res
2114 .errors
2115 .iter()
2116 .any(|e| matches!(e, SyntaxError::FunctionTypeSyntax(_)));
2117 assert!(
2118 fn_type_error,
2119 "Expected FunctionTypeSyntax error, got: {:?}",
2120 res.errors
2121 );
2122 }
2123
2124 #[test]
2125 fn test_use_wildcard_parses() {
2126 use crate::components::language::use_lang::UseSelector;
2127 let lang = parse2("use Math::*;".into()).expect("parse failed");
2128 match lang {
2129 Lang::UseModule {
2130 module_path, selector, ..
2131 } => {
2132 assert_eq!(module_path, vec!["Math".to_string()]);
2133 assert_eq!(selector, UseSelector::Wildcard);
2134 }
2135 other => panic!("Expected UseModule, got {:?}", other),
2136 }
2137 }
2138
2139 #[test]
2140 fn test_use_items_parses() {
2141 use crate::components::language::use_lang::{UseItem, UseSelector};
2142 let lang = parse2("use Math::{pi, sin as s};".into()).expect("parse failed");
2143 match lang {
2144 Lang::UseModule {
2145 module_path, selector, ..
2146 } => {
2147 assert_eq!(module_path, vec!["Math".to_string()]);
2148 assert_eq!(
2149 selector,
2150 UseSelector::Items(vec![
2151 UseItem {
2152 name: "pi".to_string(),
2153 alias: None
2154 },
2155 UseItem {
2156 name: "sin".to_string(),
2157 alias: Some("s".to_string())
2158 },
2159 ])
2160 );
2161 }
2162 other => panic!("Expected UseModule, got {:?}", other),
2163 }
2164 }
2165
2166 #[test]
2167 fn test_use_nested_path_parses() {
2168 use crate::components::language::use_lang::UseSelector;
2169 let lang = parse2("use Aa::Bb::Cc::*;".into()).expect("parse failed");
2170 match lang {
2171 Lang::UseModule {
2172 module_path, selector, ..
2173 } => {
2174 assert_eq!(module_path, vec!["Aa".to_string(), "Bb".to_string(), "Cc".to_string()]);
2175 assert_eq!(selector, UseSelector::Wildcard);
2176 }
2177 other => panic!("Expected UseModule, got {:?}", other),
2178 }
2179 }
2180
2181 #[test]
2182 fn test_implicit_mutate_simple_variable() {
2183 let res = implicit_mutate("x!;".into()).unwrap().1;
2184 assert_eq!(res.len(), 1);
2185 match &res[0] {
2186 Lang::Assign {
2187 identifier, expression, ..
2188 } => {
2189 assert!(matches!(identifier.as_ref(), Lang::Variable { .. }));
2190 assert!(matches!(expression.as_ref(), Lang::Variable { .. }));
2191 }
2192 other => panic!("Expected Assign, got {:?}", other),
2193 }
2194 }
2195
2196 #[test]
2197 fn test_implicit_mutate_pipeline() {
2198 let res = implicit_mutate("x |> f()!;".into()).unwrap().1;
2199 assert_eq!(res.len(), 1);
2200 match &res[0] {
2201 Lang::Assign {
2202 identifier, expression, ..
2203 } => {
2204 assert!(matches!(identifier.as_ref(), Lang::Variable { .. }));
2205 assert!(matches!(expression.as_ref(), Lang::Operator { .. }));
2206 }
2207 other => panic!("Expected Assign, got {:?}", other),
2208 }
2209 }
2210
2211 #[test]
2212 fn test_implicit_mutate_ufc() {
2213 let res = implicit_mutate("obj.method()!;".into()).unwrap().1;
2214 assert_eq!(res.len(), 1);
2215 match &res[0] {
2216 Lang::Assign { identifier, .. } => match identifier.as_ref() {
2217 Lang::Variable { name, .. } => assert_eq!(name, "obj"),
2218 other => panic!("Expected Variable identifier, got {:?}", other),
2219 },
2220 other => panic!("Expected Assign, got {:?}", other),
2221 }
2222 }
2223
2224 #[test]
2225 fn test_implicit_mutate_pipeline_chained() {
2226 let res = implicit_mutate("x |> f() |> g()!;".into()).unwrap().1;
2227 assert_eq!(res.len(), 1);
2228 match &res[0] {
2229 Lang::Assign { identifier, .. } => match identifier.as_ref() {
2230 Lang::Variable { name, .. } => assert_eq!(name, "x"),
2231 other => panic!("Expected Variable identifier, got {:?}", other),
2232 },
2233 other => panic!("Expected Assign, got {:?}", other),
2234 }
2235 }
2236
2237 #[test]
2238 fn test_implicit_mutate_ufc_pipeline() {
2239 let res = implicit_mutate("shape.scale(2) |> rotate(90)!;".into()).unwrap().1;
2240 assert_eq!(res.len(), 1);
2241 match &res[0] {
2242 Lang::Assign { identifier, .. } => match identifier.as_ref() {
2243 Lang::Variable { name, .. } => assert_eq!(name, "shape"),
2244 other => panic!("Expected Variable identifier, got {:?}", other),
2245 },
2246 other => panic!("Expected Assign, got {:?}", other),
2247 }
2248 }
2249
2250 #[test]
2251 fn test_implicit_mutate_invalid_literal_fails() {
2252 let res = implicit_mutate("3!;".into());
2254 assert!(res.is_err(), "Literal mutation should fail to parse");
2255 }
2256
2257 #[test]
2265 fn test_implicit_mutate_dollar_target_fails() {
2266 let res = implicit_mutate("p$x!;".into());
2268 assert!(
2269 res.is_err(),
2270 "Mutating a `$`-field target should fail to parse, not silently drop"
2271 );
2272 }
2273
2274 #[test]
2275 fn test_implicit_mutate_array_indexing_target_fails() {
2276 let res = implicit_mutate("v[1]!;".into());
2278 assert!(
2279 res.is_err(),
2280 "Mutating an indexed target should fail to parse, not silently drop"
2281 );
2282 }
2283}