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::type_alias;
39use nom::branch::alt;
40use nom::bytes::complete::tag;
41use nom::character::complete::line_ending;
42use nom::character::complete::multispace0;
43use nom::character::complete::not_line_ending;
44use nom::combinator::map;
45use nom::combinator::opt;
46use nom::multi::many0;
47use nom::multi::separated_list0;
48use nom::sequence::delimited;
49use nom::sequence::pair;
50use nom::sequence::preceded;
51use nom::sequence::terminated;
52use nom::IResult;
53use nom::Parser;
54use nom_locate::LocatedSpan;
55use std::ops::Deref;
56
57type Span<'a> = LocatedSpan<&'a str, String>;
58
59use std::cell::RefCell;
60
61thread_local! {
62 static PARSE_ERRORS: RefCell<Vec<SyntaxError>> = const { RefCell::new(Vec::new()) };
63}
64
65fn push_parse_error(err: SyntaxError) {
66 PARSE_ERRORS.with(|e| e.borrow_mut().push(err));
67}
68
69fn take_parse_errors() -> Vec<SyntaxError> {
70 PARSE_ERRORS.with(|e| e.borrow_mut().drain(..).collect())
71}
72
73#[derive(Debug, Clone)]
75pub struct ParseResult {
76 pub ast: Lang,
77 pub errors: Vec<SyntaxError>,
78}
79
80impl ParseResult {
81 pub fn new(ast: Lang) -> Self {
82 let errors = take_parse_errors();
83 ParseResult { ast, errors }
84 }
85
86 pub fn has_errors(&self) -> bool {
87 !self.errors.is_empty()
88 }
89
90 pub fn get_ast(&self) -> &Lang {
91 &self.ast
92 }
93
94 pub fn get_clean_ast(&self) -> Lang {
95 self.ast.clone()
96 }
97}
98
99fn pattern_var(s: Span) -> IResult<Span, (Vec<Lang>, Option<String>)> {
100 let res = alt((tag_exp, variable2)).parse(s);
101 match res {
102 Ok((
103 s,
104 Lang::Tag {
105 name, value: val, ..
106 },
107 )) => {
108 if let Lang::Variable {
109 name: name2,
110 is_opaque: mutopa,
111 related_type: typ,
112 help_data: h,
113 } = *val
114 {
115 Ok((
116 s,
117 (
118 vec![Lang::Variable {
119 name: name2.to_string(),
120 is_opaque: mutopa,
121 related_type: typ,
122 help_data: h.clone(),
123 }],
124 Some(name.to_string()),
125 ),
126 ))
127 } else {
128 Ok((s, (vec![], Some(name.to_string()))))
129 }
130 }
131 Ok((
132 s,
133 Lang::Variable {
134 name,
135 is_opaque: mutopa,
136 related_type: typ,
137 help_data: h,
138 },
139 )) => Ok((
140 s,
141 (
142 vec![Lang::Variable {
143 name,
144 is_opaque: mutopa,
145 related_type: typ,
146 help_data: h.clone(),
147 }],
148 None,
149 ),
150 )),
151 Err(r) => Err(r),
152 _ => todo!(),
153 }
154}
155
156fn single_parse(s: Span) -> IResult<Span, Lang> {
157 let res = (parse_elements, opt(terminated(tag(";"), multispace0))).parse(s);
158 match res {
159 Ok((s, (exp, Some(_)))) => Ok((s, exp)),
160 Ok((s, (exp, None))) => {
161 push_parse_error(SyntaxError::ForgottenSemicolon(exp.clone().into()));
162 Ok((s, exp))
163 }
164 Err(r) => Err(r),
165 }
166}
167
168fn equality_operator(s: Span) -> IResult<Span, Span> {
169 terminated(alt((tag("="), tag("<-"))), multispace0).parse(s)
170}
171
172fn base_let_exp(s: Span) -> IResult<Span, Vec<Lang>> {
173 let res = (
174 terminated(tag("let"), multispace0),
175 pattern_var,
176 opt(preceded(terminated(tag(":"), multispace0), ltype)),
177 equality_operator,
178 single_parse,
179 )
180 .parse(s);
181 match res {
182 Ok((
183 s,
184 (
185 _let,
186 (pat_var, None),
187 typ,
188 _eq,
189 Lang::Function {
190 parameters: params,
191 return_type: ty,
192 body,
193 help_data: h,
194 },
195 ),
196 )) if !params.is_empty() => {
197 let newvar = Var::from_language(pat_var[0].clone())
198 .unwrap()
199 .set_type(params[0].1.clone());
200 if let Lang::Variable {
201 name, help_data, ..
202 } = &pat_var[0]
203 {
204 if name.chars().next().is_some_and(|c| c.is_uppercase()) {
205 push_parse_error(SyntaxError::LetInsteadOfType {
206 name: name.clone(),
207 help_data: help_data.clone(),
208 });
209 }
210 }
211 Ok((
212 s,
213 vec![Lang::Let {
214 variable: Box::new(newvar.to_language()),
215 r#type: typ.unwrap_or(Type::Empty(HelpData::default())),
216 expression: Box::new(Lang::Function {
217 parameters: params,
218 return_type: ty,
219 body,
220 help_data: h,
221 }),
222 is_public: false,
223 is_testable: false,
224 is_export: false,
225 help_data: _let.into(),
226 }],
227 ))
228 }
229 Ok((s, (_let, (pat_var, None), typ, _eq, body))) => {
230 if let Lang::Variable {
231 name, help_data, ..
232 } = &pat_var[0]
233 {
234 if name.chars().next().is_some_and(|c| c.is_uppercase()) {
235 push_parse_error(SyntaxError::LetInsteadOfType {
236 name: name.clone(),
237 help_data: help_data.clone(),
238 });
239 }
240 }
241 Ok((
242 s,
243 vec![Lang::Let {
244 variable: Box::new(pat_var[0].clone()),
245 r#type: typ.clone().unwrap_or(Type::Empty(HelpData::default())),
246 expression: Box::new(body),
247 is_public: false,
248 is_testable: false,
249 is_export: false,
250 help_data: _let.into(),
251 }],
252 ))
253 }
254 Ok((s, (_let, (pat_var, Some(_)), typ, eq, body))) => {
255 if pat_var.len() == 1 {
256 Ok((
257 s,
258 vec![Lang::Let {
259 variable: Box::new(pat_var[0].clone()),
260 r#type: typ.clone().unwrap_or(Type::Empty(HelpData::default())),
261 expression: Box::new(Lang::Operator {
262 operator: Op::Dollar(HelpData::default()),
263 rhs: Box::new(Lang::Number {
264 value: 0.0,
265 help_data: eq.into(),
266 }),
267 lhs: Box::new(body),
268 help_data: pat_var.into(),
269 }),
270 is_public: false,
271 is_testable: false,
272 is_export: false,
273 help_data: _let.into(),
274 }],
275 ))
276 } else {
277 Ok((
278 s,
279 pat_var
280 .iter()
281 .map(|x| Lang::Let {
282 variable: Box::new(x.clone()),
283 r#type: typ.clone().unwrap_or(Type::Empty(HelpData::default())),
284 expression: Box::new(body.clone()),
285 is_public: false,
286 is_testable: false,
287 is_export: false,
288 help_data: HelpData::default(),
289 })
290 .collect::<Vec<_>>(),
291 ))
292 }
293 }
294 Err(r) => Err(r),
295 }
296}
297
298fn let_tuple_exp(s: Span) -> IResult<Span, Vec<Lang>> {
299 let res = (
300 terminated(tag("let"), multispace0),
301 tuple_exp,
302 opt(preceded(terminated(tag(":"), multispace0), ltype)),
303 equality_operator,
304 single_parse,
305 )
306 .parse(s);
307 match res {
308 Ok((
309 s,
310 (
311 _let,
312 Lang::Tuple {
313 value: elements,
314 help_data: _th,
315 },
316 typ,
317 _eq,
318 body,
319 ),
320 )) => {
321 let tmp_name = "__tuple_tmp__";
322 let tmp_var = Var::from_name(tmp_name).to_language();
323
324 let tmp_let = Lang::Let {
326 variable: Box::new(tmp_var.clone()),
327 r#type: typ.unwrap_or(Type::Empty(HelpData::default())),
328 expression: Box::new(body),
329 is_public: false,
330 is_testable: false,
331 is_export: false,
332 help_data: _let.into(),
333 };
334
335 let mut result = vec![tmp_let];
337 for (i, elem) in elements.iter().enumerate() {
338 if let Lang::Variable { name, .. } = elem {
339 if name == "_" {
340 continue; }
342 }
343 result.push(Lang::Let {
344 variable: Box::new(elem.clone()),
345 r#type: Type::Empty(HelpData::default()),
346 expression: Box::new(Lang::Operator {
347 operator: Op::Dot(HelpData::default()),
348 rhs: Box::new(Lang::Integer {
349 value: (i + 1) as i32,
350 help_data: HelpData::default(),
351 }),
352 lhs: Box::new(tmp_var.clone()),
353 help_data: HelpData::default(),
354 }),
355 is_public: false,
356 is_testable: false,
357 is_export: false,
358 help_data: HelpData::default(),
359 });
360 }
361
362 Ok((s, result))
363 }
364 Ok(_) => unreachable!("tuple_exp always returns Lang::Tuple"),
365 Err(r) => Err(r),
366 }
367}
368
369fn let_exp(s: Span) -> IResult<Span, Vec<Lang>> {
370 let res = (
371 opt(terminated(
372 alt((tag("@export"), tag("@pub"), tag("@testable"))),
373 multispace0,
374 )),
375 base_let_exp,
376 )
377 .parse(s);
378 match res {
379 Ok((s, (None, le))) => Ok((s, le)),
380 Ok((s, (Some(annotation), le))) => {
381 let frag = *annotation.fragment();
385 let is_pub = frag == "@pub" || frag == "@export";
386 let is_test = frag == "@testable" || frag == "@pub" || frag == "@export";
387 let is_exp = frag == "@export";
388 let new_le = le
389 .iter()
390 .map(|x| match x {
391 Lang::Let {
392 variable: var,
393 r#type: typ,
394 expression: body,
395 is_public: _,
396 is_testable: _,
397 is_export: _,
398 help_data: h,
399 } => {
400 let vari = Var::from_language(var.deref().clone())
401 .unwrap()
402 .to_language();
403 Lang::Let {
404 variable: Box::new(vari),
405 r#type: typ.clone(),
406 expression: body.clone(),
407 is_public: is_pub,
408 is_testable: is_test,
409 is_export: is_exp,
410 help_data: h.clone(),
411 }
412 }
413 lan => lan.clone(),
414 })
415 .collect();
416 Ok((s, new_le))
417 }
418 Err(r) => Err(r),
419 }
420}
421
422fn typeconstructor_exp(s: Span) -> IResult<Span, Vec<Lang>> {
426 let res = (
427 terminated(tag("typeconstructor"), multispace0),
428 pascal_case_no_space,
429 delimited(
430 terminated(tag("["), multispace0),
431 separated_list0(
432 terminated(tag(","), multispace0),
433 terminated(ltype, multispace0),
434 ),
435 terminated(tag("]"), multispace0),
436 ),
437 terminated(alt((tag("recursive"), tag("record"))), multispace0),
438 terminated(tag(";"), multispace0),
439 )
440 .parse(s);
441 match res {
442 Ok((s, (_kw, (name, h), params, category, _semi))) => {
443 let category = match *category.fragment() {
444 "recursive" => ConstructorCategory::Recursive,
445 _ => ConstructorCategory::Record,
446 };
447 Ok((
448 s,
449 vec![Lang::TypeConstructor {
450 name,
451 parameters: params,
452 category,
453 help_data: h,
454 }],
455 ))
456 }
457 Err(r) => Err(r),
458 }
459}
460
461fn base_type_exp(s: Span) -> IResult<Span, Lang> {
462 let res = (
463 terminated(tag("type"), multispace0),
464 type_alias,
465 equality_operator,
466 ltype,
467 terminated(tag(";"), multispace0),
468 )
469 .parse(s);
470 match res {
471 Ok((s, (_ty, Type::Alias(name, params, _, h), _eq, ty, _))) => {
472 let h2 = if !params.is_empty() {
473 params[0].clone().into()
474 } else {
475 HelpData::default()
476 };
477 let vari = Var::from_name(&name)
478 .set_type(Type::Params(params.clone(), h2))
479 .to_language();
480 Ok((
481 s,
482 Lang::Alias {
483 identifier: Box::new(vari),
484 parameters: params,
485 target_type: ty,
486 is_public: false,
487 help_data: h,
488 },
489 ))
490 }
491 Ok((s, (_ty, _, _eq, _ty2, _))) => Ok((s, Lang::Empty(_ty.into()))),
492 Err(r) => Err(r),
493 }
494}
495
496fn type_exp(s: Span) -> IResult<Span, Vec<Lang>> {
497 let res = (opt(terminated(tag("@pub"), multispace0)), base_type_exp).parse(s);
498 match res {
499 Ok((
500 s,
501 (
502 Some(_pu),
503 Lang::Alias {
504 identifier: var,
505 parameters: params,
506 target_type: typ,
507 help_data: h,
508 ..
509 },
510 ),
511 )) => Ok((
512 s,
513 vec![Lang::Alias {
514 identifier: var,
515 parameters: params,
516 target_type: typ,
517 is_public: true,
518 help_data: h,
519 }],
520 )),
521 Ok((
522 s,
523 (
524 None,
525 Lang::Alias {
526 identifier: var,
527 parameters: params,
528 target_type: typ,
529 help_data: h,
530 ..
531 },
532 ),
533 )) => {
534 let vari = Var::from_language(var.deref().clone())
535 .unwrap()
536 .to_language();
537 Ok((
538 s,
539 vec![Lang::Alias {
540 identifier: Box::new(vari),
541 parameters: params,
542 target_type: typ,
543 is_public: false,
544 help_data: h,
545 }],
546 ))
547 }
548 Err(r) => Err(r),
549 _ => todo!(),
550 }
551}
552
553fn type_instead_of_let_exp(s: Span) -> IResult<Span, Vec<Lang>> {
556 let res = (
557 opt(terminated(tag("@pub"), multispace0)),
558 terminated(tag("type"), multispace0),
559 terminated(variable_exp, multispace0),
560 equality_operator,
561 single_parse,
562 )
563 .parse(s);
564 match res {
565 Ok((s, (pub_ann, type_kw, (name, h), _eq, body))) => {
566 push_parse_error(SyntaxError::TypeInsteadOfLet {
567 name: name.clone(),
568 help_data: h.clone(),
569 });
570 let is_pub = pub_ann.is_some();
571 Ok((
572 s,
573 vec![Lang::Let {
574 variable: Box::new(Lang::Variable {
575 name,
576 is_opaque: false,
577 related_type: Type::Empty(HelpData::default()),
578 help_data: h,
579 }),
580 r#type: Type::Empty(type_kw.clone().into()),
581 expression: Box::new(body),
582 is_public: is_pub,
583 is_testable: is_pub,
584 is_export: false,
585 help_data: type_kw.into(),
586 }],
587 ))
588 }
589 Err(r) => Err(r),
590 }
591}
592
593fn base_opaque_exp(s: Span) -> IResult<Span, Lang> {
594 let res = (
595 terminated(tag("opaque"), multispace0),
596 type_alias,
597 equality_operator,
598 ltype,
599 terminated(tag(";"), multispace0),
600 )
601 .parse(s);
602 match res {
603 Ok((s, (_ty, Type::Alias(name, params, _, h), _eq, ty, _))) => {
604 let vari = Var::from_name(&name)
605 .set_type(Type::Params(params.clone(), params.clone().into()))
606 .set_opacity(true)
607 .to_language();
608 Ok((
609 s,
610 Lang::Alias {
611 identifier: Box::new(vari),
612 parameters: params,
613 target_type: ty,
614 is_public: false,
615 help_data: h,
616 },
617 ))
618 }
619 Ok((s, (_ty, _, _eq, _ty2, _))) => Ok((s, Lang::Empty(_ty.into()))),
620 Err(r) => Err(r),
621 }
622}
623
624fn opaque_exp(s: Span) -> IResult<Span, Vec<Lang>> {
625 let res = (opt(terminated(tag("@pub"), multispace0)), base_opaque_exp).parse(s);
626 match res {
627 Ok((
628 s,
629 (
630 Some(_pu),
631 Lang::Alias {
632 identifier: var,
633 parameters: params,
634 target_type: typ,
635 help_data: h,
636 ..
637 },
638 ),
639 )) => {
640 let vari = Var::from_language(var.deref().clone())
641 .unwrap()
642 .set_opacity(true)
643 .to_language();
644 Ok((
645 s,
646 vec![Lang::Alias {
647 identifier: Box::new(vari),
648 parameters: params,
649 target_type: typ,
650 is_public: true,
651 help_data: h,
652 }],
653 ))
654 }
655 Ok((
656 s,
657 (
658 None,
659 Lang::Alias {
660 identifier: var,
661 parameters: params,
662 target_type: typ,
663 help_data: h,
664 ..
665 },
666 ),
667 )) => {
668 let vari = Var::from_language(var.deref().clone())
669 .unwrap()
670 .set_opacity(true)
671 .to_language();
672 Ok((
673 s,
674 vec![Lang::Alias {
675 identifier: Box::new(vari),
676 parameters: params,
677 target_type: typ,
678 is_public: false,
679 help_data: h,
680 }],
681 ))
682 }
683 Err(r) => Err(r),
684 _ => todo!(),
685 }
686}
687
688pub fn module(s: Span) -> IResult<Span, Vec<Lang>> {
689 let res = (
690 terminated(tag("module"), multispace0),
691 terminated(variable_recognizer, multispace0),
692 terminated(tag("{"), multispace0),
693 base_parse,
694 terminated(tag("}"), multispace0),
695 opt(terminated(tag(";"), multispace0)),
696 )
697 .parse(s);
698 match res {
699 Ok((s, (modu, (name, _), _op, v, _cl, _dv))) => Ok((
700 s,
701 vec![Lang::Module {
702 name,
703 body: v,
704 module_position: ModulePosition::Internal,
705 config: Config::default(),
706 help_data: modu.into(),
707 }],
708 )),
709 Err(r) => Err(r),
710 }
711}
712
713fn import_module(s: Span) -> IResult<Span, Vec<Lang>> {
714 let res = (
715 terminated(tag("import"), multispace0),
716 terminated(variable_recognizer, multispace0),
717 opt((
718 terminated(tag("as"), multispace0),
719 terminated(variable_recognizer, multispace0),
720 )),
721 opt(terminated(tag(";"), multispace0)),
722 )
723 .parse(s);
724 match res {
725 Ok((s, (import_kw, (name, _), None, _))) => Ok((
726 s,
727 vec![Lang::ModuleImport {
728 value: name,
729 help_data: import_kw.into(),
730 }],
731 )),
732 Ok((s, (_, (name, h), Some((_, (alias, _))), _))) => {
733 let module_var = Lang::Variable {
734 name,
735 is_opaque: false,
736 related_type: Type::Empty(HelpData::default()),
737 help_data: h.clone(),
738 };
739 let alias_var = Var::from_name(&alias).to_language();
740 Ok((
741 s,
742 vec![Lang::Let {
743 variable: Box::new(alias_var),
744 r#type: Type::Empty(HelpData::default()),
745 expression: Box::new(module_var),
746 is_public: false,
747 is_testable: false,
748 is_export: false,
749 help_data: h,
750 }],
751 ))
752 }
753 Err(r) => Err(r),
754 }
755}
756
757fn assign(s: Span) -> IResult<Span, Vec<Lang>> {
758 let res = (
759 variable,
760 alt((
761 terminated(tag("="), multispace0),
762 terminated(tag("<-"), multispace0),
763 )),
764 parse_elements,
765 opt(terminated(tag(";"), multispace0)),
766 )
767 .parse(s);
768 match res {
769 Ok((s, ((var, _), _eq, exp, Some(_)))) => Ok((
770 s,
771 vec![Lang::Assign {
772 identifier: Box::new(var.clone()),
773 expression: Box::new(exp),
774 help_data: var.into(),
775 }],
776 )),
777 Ok((s, ((var, _), _eq, exp, None))) => {
778 push_parse_error(SyntaxError::ForgottenSemicolon(exp.clone().into()));
779 let assign = Lang::Assign {
780 identifier: Box::new(var.clone()),
781 expression: Box::new(exp),
782 help_data: var.into(),
783 };
784 Ok((s, vec![assign]))
785 }
786 Err(r) => Err(r),
787 }
788}
789
790fn comment(s: Span) -> IResult<Span, Vec<Lang>> {
791 let res = (tag("#"), not_line_ending, opt(line_ending), multispace0).parse(s);
792 match res {
793 Ok((s, (_hashtag, txt, _, _))) => Ok((
794 s,
795 vec![Lang::Comment {
796 value: txt.to_string(),
797 help_data: _hashtag.into(),
798 }],
799 )),
800 Err(r) => Err(r),
801 }
802}
803
804pub fn simple_exp(s: Span) -> IResult<Span, Vec<Lang>> {
805 let res = (parse_elements, opt(terminated(tag(";"), multispace0))).parse(s);
806 match res {
807 Ok((s, (lang, Some(_)))) => Ok((s, vec![lang])),
808 Ok((s, (lang, None))) => {
809 push_parse_error(SyntaxError::ForgottenSemicolon(lang.clone().into()));
810 Ok((s, vec![lang]))
811 }
812 Err(r) => Err(r),
813 }
814}
815
816fn mod_imp(s: Span) -> IResult<Span, Vec<Lang>> {
817 let res = (
818 terminated(tag("mod"), multispace0),
819 terminated(variable_exp, multispace0),
820 terminated(tag(";"), multispace0),
821 )
822 .parse(s);
823 match res {
824 Ok((s, (_mod, (name, _), _sc))) => Ok((
825 s,
826 vec![Lang::ModuleImport {
827 value: name.to_string(),
828 help_data: _mod.into(),
829 }],
830 )),
831 Err(r) => Err(r),
832 }
833}
834
835fn import_var(s: Span) -> IResult<Span, Vec<Lang>> {
836 let res = (
837 terminated(tag("use"), multispace0),
838 variable,
839 terminated(tag(";"), multispace0),
840 )
841 .parse(s);
842 match res {
843 Ok((s, (_use, (lang, case), _sc))) => {
844 let res = match case {
845 Case::Maj => Var::from_language(lang).unwrap().to_alias_lang(),
846 _ => Var::from_language(lang).unwrap().to_let(),
847 };
848 Ok((s, vec![res]))
849 }
850 Err(r) => Err(r),
851 }
852}
853
854fn import_type(s: Span) -> IResult<Span, Vec<Lang>> {
855 let res = (
856 terminated(tag("use"), multispace0),
857 type_alias,
858 terminated(tag(";"), multispace0),
859 )
860 .parse(s);
861
862 match res {
863 Ok((s, (_use, alias, _sc))) => Ok((
864 s,
865 vec![Lang::Import {
866 value: alias,
867 help_data: _use.into(),
868 }],
869 )),
870 Err(r) => Err(r),
871 }
872}
873
874fn tests(s: Span) -> IResult<Span, Vec<Lang>> {
875 let res = (tag("Test"), delimited(tag("["), base_parse, tag("]"))).parse(s);
876 match res {
877 Ok((s, (_t, body))) => Ok((
878 s,
879 vec![Lang::Test {
880 value: body,
881 help_data: _t.into(),
882 }],
883 )),
884 Err(r) => Err(r),
885 }
886}
887
888fn library(s: Span) -> IResult<Span, Vec<Lang>> {
889 let res = (
890 tag("library("),
891 variable_exp,
892 tag(")"),
893 opt(tag(";")),
894 multispace0,
895 )
896 .parse(s);
897
898 match res {
899 Ok((s, (_lib, (var, h), _cl, Some(_col), _))) => Ok((
900 s,
901 vec![Lang::Library {
902 value: var,
903 help_data: h.clone(),
904 }],
905 )),
906 Ok((_, (_lib, _var, _cl, None, _))) => {
907 panic!("You forgot to put a ';' at the end of the line")
908 }
909 Err(r) => Err(r),
910 }
911}
912
913fn use_item_exp(s: Span) -> IResult<Span, crate::components::language::use_lang::UseItem> {
914 use crate::components::language::use_lang::UseItem;
915 let res = (
917 terminated(variable_recognizer, multispace0),
918 opt(preceded(
919 pair(tag("as"), multispace0),
920 terminated(variable_recognizer, multispace0),
921 )),
922 )
923 .parse(s);
924 match res {
925 Ok((s, ((name, _), alias_opt))) => {
926 let alias = alias_opt.map(|(alias_name, _)| alias_name);
927 Ok((s, UseItem { name, alias }))
928 }
929 Err(r) => Err(r),
930 }
931}
932
933fn use_items_selector(
934 s: Span,
935) -> IResult<Span, crate::components::language::use_lang::UseSelector> {
936 use crate::components::language::use_lang::UseSelector;
937 let res = (
938 pair(tag("{"), multispace0),
939 separated_list0(pair(tag(","), multispace0), use_item_exp),
940 opt(pair(tag(","), multispace0)),
941 pair(tag("}"), multispace0),
942 )
943 .parse(s);
944 match res {
945 Ok((s, (_, items, _, _))) => Ok((s, UseSelector::Items(items))),
946 Err(r) => Err(r),
947 }
948}
949
950fn use_selector_exp(s: Span) -> IResult<Span, crate::components::language::use_lang::UseSelector> {
951 use crate::components::language::use_lang::UseSelector;
952 alt((
953 map(terminated(tag("*"), multispace0), |_| UseSelector::Wildcard),
954 use_items_selector,
955 ))
956 .parse(s)
957}
958
959fn use_module_directive(s: Span) -> IResult<Span, Vec<Lang>> {
960 use crate::components::language::use_lang::UseSelector;
961
962 let res = (
964 terminated(tag("use"), multispace0),
965 terminated(variable_recognizer, multispace0),
966 pair(tag("::"), multispace0),
967 )
968 .parse(s);
969
970 let (s, (use_kw, (first_seg, _), _)) = res?;
971
972 let mut path = vec![first_seg];
973 let mut current_s = s;
974 let selector;
975
976 loop {
977 match use_selector_exp(current_s.clone()) {
978 Ok((s2, sel)) => {
979 selector = sel;
980 current_s = s2;
981 break;
982 }
983 Err(_) => match terminated(variable_recognizer, multispace0).parse(current_s.clone()) {
984 Ok((s2, (seg, _))) => {
985 let colon_res: IResult<Span, (Span, Span)> =
986 pair(tag("::"), multispace0).parse(s2.clone());
987 match colon_res {
988 Ok((s3, _)) => {
989 path.push(seg);
990 current_s = s3;
991 }
992 Err(_) => {
993 use crate::components::language::use_lang::UseItem;
994 selector = UseSelector::Items(vec![UseItem {
995 name: seg,
996 alias: None,
997 }]);
998 current_s = s2;
999 break;
1000 }
1001 }
1002 }
1003 Err(e) => return Err(e),
1004 },
1005 }
1006 }
1007
1008 let res = terminated(tag(";"), multispace0).parse(current_s);
1009 let (s, _) = res?;
1010
1011 Ok((
1012 s,
1013 vec![Lang::UseModule {
1014 module_path: path,
1015 selector,
1016 help_data: use_kw.into(),
1017 }],
1018 ))
1019}
1020
1021fn use_exp(s: Span) -> IResult<Span, Vec<Lang>> {
1022 let res = (
1023 tag("use("),
1024 chars,
1025 tag(", "),
1026 alt((vector, chars)),
1027 terminated(tag(");"), multispace0),
1028 )
1029 .parse(s);
1030 match res {
1031 Ok((s, (us, lib, _, members, _))) => Ok((
1032 s,
1033 vec![Lang::Use {
1034 lang: Box::new(lib),
1035 members: Box::new(members),
1036 help_data: us.into(),
1037 }],
1038 )),
1039 Err(r) => Err(r),
1040 }
1041}
1042
1043fn custom_operators(s: Span) -> IResult<Span, (String, HelpData)> {
1044 let res = custom_op.parse(s);
1045 match res {
1046 Ok((s, co)) => Ok((s, (co.clone().to_string(), co.into()))),
1047 Err(r) => Err(r),
1048 }
1049}
1050
1051fn return_stmt(s: Span) -> IResult<Span, Vec<Lang>> {
1052 let (s, e) = return_exp(s)?;
1053 Ok((s, vec![e]))
1054}
1055
1056fn stmt_exp(s: Span) -> IResult<Span, Vec<Lang>> {
1057 let res = (parse_elements, terminated(tag(";"), multispace0)).parse(s);
1058 match res {
1059 Ok((s, (lang, _))) => Ok((s, vec![lang])),
1060 Err(r) => Err(r),
1061 }
1062}
1063
1064fn head_lang(lang: &Lang) -> Option<Lang> {
1065 match lang {
1066 Lang::Variable { .. } => Some(lang.clone()),
1067 Lang::Operator {
1068 operator: Op::Pipe(_) | Op::Dot(_),
1069 rhs,
1070 ..
1071 } => head_lang(rhs),
1072 _ => None,
1073 }
1074}
1075
1076fn implicit_mutate(s: Span) -> IResult<Span, Vec<Lang>> {
1077 let res = (parse_elements, terminated(tag("!;"), multispace0)).parse(s);
1078 match res {
1079 Ok((s, (expr, excl))) => match head_lang(&expr) {
1080 Some(lhs) => Ok((
1081 s,
1082 vec![Lang::Assign {
1083 identifier: Box::new(lhs),
1084 expression: Box::new(expr),
1085 help_data: excl.into(),
1086 }],
1087 )),
1088 None => {
1089 push_parse_error(SyntaxError::MutationTargetNotAssignable(
1090 expr.clone().into(),
1091 ));
1092 Err(nom::Err::Error(nom::error::Error::new(
1093 s,
1094 nom::error::ErrorKind::Tag,
1095 )))
1096 }
1097 },
1098 Err(r) => Err(r),
1099 }
1100}
1101
1102fn signature_variable(s: Span) -> IResult<Span, Vec<Lang>> {
1103 let res = (
1104 tag("@"),
1105 alt((variable_recognizer, custom_operators)),
1106 terminated(tag(":"), multispace0),
1107 ltype,
1108 terminated(tag(";"), multispace0),
1109 )
1110 .parse(s);
1111 match res {
1112 Ok((s, (at, (name, h), _col, typ, _))) => {
1113 let var2 = Var::from_name(&name).set_help_data(h).set_type(typ.clone());
1114 Ok((
1115 s,
1116 vec![Lang::Signature {
1117 identifier: var2,
1118 target_type: typ,
1119 help_data: at.into(),
1120 }],
1121 ))
1122 }
1123 Err(r) => Err(r),
1124 }
1125}
1126
1127fn signature_opaque(s: Span) -> IResult<Span, Vec<Lang>> {
1128 let res = (
1129 tag("@"),
1130 type_alias,
1131 terminated(tag(":"), multispace0),
1132 ltype,
1133 terminated(tag(";"), multispace0),
1134 )
1135 .parse(s);
1136 match res {
1137 Ok((s, (at, Type::Alias(name, _params, _, h), _, typ, _))) => {
1138 let var2 = Var::from_name(&name)
1139 .set_help_data(h.clone())
1140 .set_type(typ.clone());
1141 Ok((
1142 s,
1143 vec![Lang::Signature {
1144 identifier: var2,
1145 target_type: typ,
1146 help_data: at.into(),
1147 }],
1148 ))
1149 }
1150 Ok((_s, (_, _, _, _, _))) => todo!(),
1151 Err(r) => Err(r),
1152 }
1153}
1154
1155pub fn signature(s: Span) -> IResult<Span, Vec<Lang>> {
1156 alt((signature_opaque, signature_variable)).parse(s)
1157}
1158
1159fn for_loop(s: Span) -> IResult<Span, Vec<Lang>> {
1160 let res = (
1161 terminated(tag("for"), multispace0),
1162 terminated(tag("("), multispace0),
1163 terminated(variable_exp, multispace0),
1164 terminated(tag("in"), multispace0),
1165 terminated(single_element, multispace0),
1166 terminated(tag(")"), multispace0),
1167 scope,
1168 terminated(tag(";"), multispace0),
1169 )
1170 .parse(s);
1171 match res {
1172 Ok((s, (_for, _op, (var_str, _h), _in, iterator, _cl, scop, _semi))) => Ok((
1173 s,
1174 vec![Lang::ForLoop {
1175 identifier: Var::from_name(&var_str),
1176 expression: Box::new(iterator),
1177 body: Box::new(scop),
1178 help_data: _for.into(),
1179 }],
1180 )),
1181 Err(r) => Err(r),
1182 }
1183}
1184
1185fn while_loop(s: Span) -> IResult<Span, Vec<Lang>> {
1186 let res = (
1187 terminated(tag("while"), multispace0),
1188 terminated(tag("("), multispace0),
1189 terminated(single_element, multispace0),
1190 terminated(tag(")"), multispace0),
1191 scope,
1192 terminated(tag(";"), multispace0),
1193 )
1194 .parse(s);
1195 match res {
1196 Ok((s, (_while, _op, condition, _cl, scop, _semi))) => Ok((
1197 s,
1198 vec![Lang::WhileLoop {
1199 condition: Box::new(condition),
1200 body: Box::new(scop),
1201 help_data: _while.into(),
1202 }],
1203 )),
1204 Err(r) => Err(r),
1205 }
1206}
1207
1208fn loop_loop(s: Span) -> IResult<Span, Vec<Lang>> {
1209 let res = (
1210 terminated(tag("loop"), multispace0),
1211 scope,
1212 terminated(tag(";"), multispace0),
1213 )
1214 .parse(s);
1215 match res {
1216 Ok((s, (_loop, scop, _semi))) => Ok((
1217 s,
1218 vec![Lang::Loop {
1219 body: Box::new(scop),
1220 help_data: _loop.into(),
1221 }],
1222 )),
1223 Err(r) => Err(r),
1224 }
1225}
1226
1227fn test_block(s: Span) -> IResult<Span, Vec<Lang>> {
1228 let res = (terminated(tag("Test"), multispace0), scope).parse(s);
1229 match res {
1232 Ok((s, (tst, body))) => Ok((
1233 s,
1234 vec![Lang::TestBlock {
1235 value: Box::new(body),
1236 help_data: tst.into(),
1237 }],
1238 )),
1239 Err(r) => Err(r),
1240 }
1241}
1242
1243pub fn base_parse(s: Span) -> IResult<Span, Vec<Lang>> {
1245 let res = (
1246 opt(multispace0),
1247 many0(alt((
1248 alt((
1249 library,
1250 break_exp,
1251 next_exp,
1252 use_exp,
1253 test_block,
1254 while_loop,
1255 loop_loop,
1256 for_loop,
1257 signature,
1258 tests,
1259 import_module,
1260 use_module_directive,
1261 import_type,
1262 )),
1263 alt((
1264 import_var,
1265 mod_imp,
1266 comment,
1267 typeconstructor_exp,
1268 type_exp,
1269 type_instead_of_let_exp,
1270 opaque_exp,
1271 let_tuple_exp,
1272 let_exp,
1273 module,
1274 assign,
1275 return_stmt,
1276 implicit_mutate,
1277 stmt_exp,
1278 )),
1279 ))),
1280 opt(parse_elements),
1281 )
1282 .parse(s);
1283 match res {
1284 Ok((s, (_, v, None))) if v.is_empty() => Ok((s, vec![])),
1286 Ok((s, (_, v, Some(expr)))) if v.is_empty() => Ok((s, vec![expr])),
1288 Ok((s, (_, v, trailing))) => {
1290 let mut result: Vec<Lang> = v.into_iter().flatten().collect();
1291 if let Some(expr) = trailing {
1292 result.push(expr);
1293 }
1294 Ok((s, result))
1295 }
1296 Err(r) => Err(r),
1297 }
1298}
1299
1300pub fn parse(s: Span) -> ParseResult {
1305 let res = base_parse(s.clone());
1306 match res {
1307 Ok((remaining, v)) => {
1308 if !remaining.fragment().is_empty() {
1309 let element = remaining
1310 .fragment()
1311 .lines()
1312 .next()
1313 .unwrap_or("")
1314 .trim()
1315 .to_string();
1316 let line = remaining.location_line();
1317 let help_data = HelpData::from(remaining);
1318 push_parse_error(SyntaxError::UnknownElement {
1319 element,
1320 line,
1321 help_data,
1322 });
1323 }
1324 ParseResult::new(Lang::Lines {
1325 value: v.clone(),
1326 help_data: v.into(),
1327 })
1328 }
1329 Err(_) => panic!("Can't parse string {}", s),
1330 }
1331}
1332
1333pub fn parse_legacy(s: Span) -> Lang {
1338 parse(s).ast
1339}
1340
1341pub fn parse2(s: Span) -> Result<Lang, String> {
1342 let res = base_parse(s.clone());
1343 let _ = take_parse_errors();
1345 match res {
1346 Ok((_, v)) => Ok(v[0].clone()),
1347 Err(_) => Err(format!("Can't parse string {}", s)),
1348 }
1349}
1350
1351pub fn parse_from_string(source: &str, filename: &str) -> Lang {
1356 use crate::components::error_message::help_data::register_source;
1357
1358 register_source(filename, source);
1360
1361 let span: Span = LocatedSpan::new_extra(source, filename.to_string());
1363
1364 parse(span).ast
1366}
1367
1368pub fn parse_from_string_with_errors(source: &str, filename: &str) -> ParseResult {
1370 use crate::components::error_message::help_data::register_source;
1371
1372 register_source(filename, source);
1374
1375 let span: Span = LocatedSpan::new_extra(source, filename.to_string());
1377
1378 parse(span)
1380}
1381
1382#[cfg(test)]
1384mod tesus {
1385 use super::*;
1386
1387 #[test]
1388 fn test_semicolon1() {
1389 let res = parse("let a <- 5".into());
1390 assert!(
1392 res.has_errors(),
1393 "Missing semicolon should produce a syntax error"
1394 );
1395 assert_eq!(res.errors.len(), 1, "Should have exactly one error");
1396 match &res.errors[0] {
1397 SyntaxError::ForgottenSemicolon(_) => (),
1398 _ => panic!("Expected ForgottenSemicolon error"),
1399 }
1400 }
1401
1402 #[test]
1403 fn test_semicolon_standalone_exp() {
1404 let res = parse("f(x)".into());
1405 assert!(
1407 !res.has_errors(),
1408 "A standalone expression without semicolon is valid (case 2)"
1409 );
1410 }
1411
1412 #[test]
1413 fn test_semicolon_assign() {
1414 let res = parse("a <- 12".into());
1415 assert!(
1416 res.has_errors(),
1417 "An assign expression without semicolon should produce a syntax error"
1418 );
1419 match &res.errors[0] {
1420 SyntaxError::ForgottenSemicolon(_) => (),
1421 _ => panic!("Expected ForgottenSemicolon error"),
1422 }
1423 }
1424
1425 #[test]
1426 fn test_assign1() {
1427 let res = assign("a <- 12;".into()).unwrap().1;
1428 assert_eq!(
1429 "Assign",
1430 res[0].simple_print(),
1431 "The expression 'a <- 12;' should be identified as an assignation"
1432 );
1433 }
1434
1435 #[test]
1438 fn test_let_instead_of_type() {
1439 let res = parse("let MyType <- int;".into());
1440 assert!(
1441 res.has_errors(),
1442 "let with PascalCase should produce a syntax error"
1443 );
1444 assert_eq!(res.errors.len(), 1, "Should have exactly one error");
1445 match &res.errors[0] {
1446 SyntaxError::LetInsteadOfType { name, .. } => {
1447 assert_eq!(name, "MyType", "Error should reference the type name");
1448 }
1449 _ => panic!("Expected LetInsteadOfType error"),
1450 }
1451 }
1452
1453 #[test]
1454 fn test_let_instead_of_type_with_pub() {
1455 let res = parse("@pub let MyAlias <- num;".into());
1456 assert!(
1457 res.has_errors(),
1458 "@pub let with PascalCase should produce a syntax error"
1459 );
1460 assert!(res
1461 .errors
1462 .iter()
1463 .any(|e| matches!(e, SyntaxError::LetInsteadOfType { .. })));
1464 }
1465
1466 #[test]
1467 fn test_let_with_lowercase_is_fine() {
1468 let res = parse("let my_var <- 42;".into());
1469 assert!(
1470 !res.has_errors(),
1471 "let with snake_case should not produce a syntax error"
1472 );
1473 }
1474
1475 #[test]
1476 fn test_type_instead_of_let() {
1477 let res = parse("type my_var <- 42;".into());
1478 assert!(
1479 res.has_errors(),
1480 "type with snake_case should produce a syntax error"
1481 );
1482 assert_eq!(res.errors.len(), 1, "Should have exactly one error");
1483 match &res.errors[0] {
1484 SyntaxError::TypeInsteadOfLet { name, .. } => {
1485 assert_eq!(name, "my_var", "Error should reference the variable name");
1486 }
1487 _ => panic!("Expected TypeInsteadOfLet error"),
1488 }
1489 }
1490
1491 #[test]
1492 fn test_type_instead_of_let_with_pub() {
1493 let res = parse("@pub type my_binding <- num;".into());
1494 assert!(
1495 res.has_errors(),
1496 "@pub type with snake_case should produce a syntax error"
1497 );
1498 assert!(res
1499 .errors
1500 .iter()
1501 .any(|e| matches!(e, SyntaxError::TypeInsteadOfLet { .. })));
1502 }
1503
1504 #[test]
1505 fn test_type_with_pascalcase_is_fine() {
1506 let res = parse("type MyAlias <- int;".into());
1507 assert!(
1508 !res.has_errors(),
1509 "type with PascalCase should not produce a syntax error"
1510 );
1511 }
1512
1513 #[test]
1516 fn test_let_tuple_basic() {
1517 let res = let_tuple_exp("let :{a, b, c} <- :{1, 2, 3};".into())
1518 .unwrap()
1519 .1;
1520 assert_eq!(
1522 res.len(),
1523 4,
1524 "Should produce 4 Let statements (1 tmp + 3 bindings)"
1525 );
1526 for item in &res {
1527 assert!(
1528 item.simple_print().starts_with("let"),
1529 "Each item should be a Let, got: {}",
1530 item.simple_print()
1531 );
1532 }
1533 }
1534
1535 #[test]
1536 fn test_let_tuple_tmp_variable() {
1537 let res = let_tuple_exp("let :{a, b} <- :{1, 2};".into()).unwrap().1;
1538 if let Lang::Let { variable: var, .. } = &res[0] {
1540 if let Lang::Variable { name, .. } = var.as_ref() {
1541 assert_eq!(name, "__tuple_tmp__");
1542 } else {
1543 panic!("Expected Variable in first Let");
1544 }
1545 } else {
1546 panic!("Expected Let");
1547 }
1548 }
1549
1550 #[test]
1551 fn test_let_tuple_bindings() {
1552 let res = let_tuple_exp("let :{x, y} <- :{10, 20};".into()).unwrap().1;
1553 if let Lang::Let {
1555 variable: var,
1556 expression: body,
1557 ..
1558 } = &res[1]
1559 {
1560 if let Lang::Variable { name, .. } = var.as_ref() {
1561 assert_eq!(name, "x");
1562 } else {
1563 panic!("Expected Variable 'x'");
1564 }
1565 assert_eq!(
1566 body.simple_print(),
1567 "Operator",
1568 "Body should be a Dot operator"
1569 );
1570 } else {
1571 panic!("Expected Let");
1572 }
1573 if let Lang::Let { variable: var, .. } = &res[2] {
1575 if let Lang::Variable { name, .. } = var.as_ref() {
1576 assert_eq!(name, "y");
1577 } else {
1578 panic!("Expected Variable 'y'");
1579 }
1580 } else {
1581 panic!("Expected Let");
1582 }
1583 }
1584
1585 #[test]
1586 fn test_let_tuple_wildcard() {
1587 let res = let_tuple_exp("let :{a, _, c} <- :{1, 2, 3};".into())
1588 .unwrap()
1589 .1;
1590 assert_eq!(
1592 res.len(),
1593 3,
1594 "Should produce 3 Let statements (wildcard skipped)"
1595 );
1596 if let Lang::Let { variable: var, .. } = &res[1] {
1598 if let Lang::Variable { name, .. } = var.as_ref() {
1599 assert_eq!(name, "a");
1600 } else {
1601 panic!("Expected Variable 'a'");
1602 }
1603 } else {
1604 panic!("Expected Let");
1605 }
1606 if let Lang::Let { variable: var, .. } = &res[2] {
1608 if let Lang::Variable { name, .. } = var.as_ref() {
1609 assert_eq!(name, "c");
1610 } else {
1611 panic!("Expected Variable 'c'");
1612 }
1613 } else {
1614 panic!("Expected Let");
1615 }
1616 }
1617
1618 #[test]
1619 fn test_let_tuple_in_full_parse() {
1620 let res = parse("let :{a, b, c} <- :{1, 2, 3};".into());
1621 assert!(
1622 !res.has_errors(),
1623 "Let tuple destructuring should parse without errors"
1624 );
1625 }
1626
1627 #[test]
1628 fn test_let_tuple_with_equals() {
1629 let res = let_tuple_exp("let :{a, b} = :{1, 2};".into()).unwrap().1;
1630 assert_eq!(res.len(), 3, "Should work with '=' operator too");
1631 }
1632
1633 #[test]
1634 fn test_let_tuple_type_check() {
1635 use crate::components::context::Context;
1636 use crate::processes::type_checking::typing;
1637 use crate::utils::builder;
1638
1639 let ast = parse("let :{a, b, c} <- :{1, 2, 3};".into()).ast;
1640 let context = Context::empty();
1641 let tc = typing(&context, &ast);
1642
1643 let ty_a = tc
1645 .context
1646 .get_type_from_existing_variable(crate::components::language::var::Var::from_name("a"));
1647 let ty_b = tc
1648 .context
1649 .get_type_from_existing_variable(crate::components::language::var::Var::from_name("b"));
1650 let ty_c = tc
1651 .context
1652 .get_type_from_existing_variable(crate::components::language::var::Var::from_name("c"));
1653
1654 assert_eq!(
1655 ty_a,
1656 builder::integer_type(1),
1657 "Variable 'a' should be Integer(1)"
1658 );
1659 assert_eq!(
1660 ty_b,
1661 builder::integer_type(2),
1662 "Variable 'b' should be Integer(2)"
1663 );
1664 assert_eq!(
1665 ty_c,
1666 builder::integer_type(3),
1667 "Variable 'c' should be Integer(3)"
1668 );
1669 }
1670
1671 #[test]
1672 fn test_let_tuple_type_check_mixed_types() {
1673 use crate::components::context::Context;
1674 use crate::processes::type_checking::typing;
1675 use crate::utils::builder;
1676
1677 let ast = parse("let :{x, y} <- :{1, 'hello'};".into()).ast;
1678 let context = Context::empty();
1679 let tc = typing(&context, &ast);
1680
1681 let ty_x = tc
1682 .context
1683 .get_type_from_existing_variable(crate::components::language::var::Var::from_name("x"));
1684 let ty_y = tc
1685 .context
1686 .get_type_from_existing_variable(crate::components::language::var::Var::from_name("y"));
1687
1688 assert_eq!(
1689 ty_x,
1690 builder::integer_type(1),
1691 "Variable 'x' should be Integer(1)"
1692 );
1693 assert_eq!(
1694 ty_y,
1695 builder::character_type("hello"),
1696 "Variable 'y' should be Character('hello')"
1697 );
1698 }
1699
1700 #[test]
1701 fn test_fn_function_type_syntax_error() {
1702 let res = parse("let f: fn(a: int) -> int <- fn(x: int): int { x };".into());
1703 assert!(
1704 res.has_errors(),
1705 "Using 'fn(...)' in type position should produce a syntax error"
1706 );
1707 let fn_type_error = res
1708 .errors
1709 .iter()
1710 .any(|e| matches!(e, SyntaxError::FunctionTypeSyntax(_)));
1711 assert!(
1712 fn_type_error,
1713 "Expected FunctionTypeSyntax error, got: {:?}",
1714 res.errors
1715 );
1716 }
1717
1718 #[test]
1719 fn test_use_wildcard_parses() {
1720 use crate::components::language::use_lang::UseSelector;
1721 let lang = parse2("use Math::*;".into()).expect("parse failed");
1722 match lang {
1723 Lang::UseModule {
1724 module_path,
1725 selector,
1726 ..
1727 } => {
1728 assert_eq!(module_path, vec!["Math".to_string()]);
1729 assert_eq!(selector, UseSelector::Wildcard);
1730 }
1731 other => panic!("Expected UseModule, got {:?}", other),
1732 }
1733 }
1734
1735 #[test]
1736 fn test_use_items_parses() {
1737 use crate::components::language::use_lang::{UseItem, UseSelector};
1738 let lang = parse2("use Math::{pi, sin as s};".into()).expect("parse failed");
1739 match lang {
1740 Lang::UseModule {
1741 module_path,
1742 selector,
1743 ..
1744 } => {
1745 assert_eq!(module_path, vec!["Math".to_string()]);
1746 assert_eq!(
1747 selector,
1748 UseSelector::Items(vec![
1749 UseItem {
1750 name: "pi".to_string(),
1751 alias: None
1752 },
1753 UseItem {
1754 name: "sin".to_string(),
1755 alias: Some("s".to_string())
1756 },
1757 ])
1758 );
1759 }
1760 other => panic!("Expected UseModule, got {:?}", other),
1761 }
1762 }
1763
1764 #[test]
1765 fn test_use_nested_path_parses() {
1766 use crate::components::language::use_lang::UseSelector;
1767 let lang = parse2("use Aa::Bb::Cc::*;".into()).expect("parse failed");
1768 match lang {
1769 Lang::UseModule {
1770 module_path,
1771 selector,
1772 ..
1773 } => {
1774 assert_eq!(
1775 module_path,
1776 vec!["Aa".to_string(), "Bb".to_string(), "Cc".to_string()]
1777 );
1778 assert_eq!(selector, UseSelector::Wildcard);
1779 }
1780 other => panic!("Expected UseModule, got {:?}", other),
1781 }
1782 }
1783
1784 #[test]
1785 fn test_implicit_mutate_simple_variable() {
1786 let res = implicit_mutate("x!;".into()).unwrap().1;
1787 assert_eq!(res.len(), 1);
1788 match &res[0] {
1789 Lang::Assign {
1790 identifier,
1791 expression,
1792 ..
1793 } => {
1794 assert!(matches!(identifier.as_ref(), Lang::Variable { .. }));
1795 assert!(matches!(expression.as_ref(), Lang::Variable { .. }));
1796 }
1797 other => panic!("Expected Assign, got {:?}", other),
1798 }
1799 }
1800
1801 #[test]
1802 fn test_implicit_mutate_pipeline() {
1803 let res = implicit_mutate("x |> f()!;".into()).unwrap().1;
1804 assert_eq!(res.len(), 1);
1805 match &res[0] {
1806 Lang::Assign {
1807 identifier,
1808 expression,
1809 ..
1810 } => {
1811 assert!(matches!(identifier.as_ref(), Lang::Variable { .. }));
1812 assert!(matches!(expression.as_ref(), Lang::Operator { .. }));
1813 }
1814 other => panic!("Expected Assign, got {:?}", other),
1815 }
1816 }
1817
1818 #[test]
1819 fn test_implicit_mutate_ufc() {
1820 let res = implicit_mutate("obj.method()!;".into()).unwrap().1;
1821 assert_eq!(res.len(), 1);
1822 match &res[0] {
1823 Lang::Assign { identifier, .. } => match identifier.as_ref() {
1824 Lang::Variable { name, .. } => assert_eq!(name, "obj"),
1825 other => panic!("Expected Variable identifier, got {:?}", other),
1826 },
1827 other => panic!("Expected Assign, got {:?}", other),
1828 }
1829 }
1830
1831 #[test]
1832 fn test_implicit_mutate_pipeline_chained() {
1833 let res = implicit_mutate("x |> f() |> g()!;".into()).unwrap().1;
1834 assert_eq!(res.len(), 1);
1835 match &res[0] {
1836 Lang::Assign { identifier, .. } => match identifier.as_ref() {
1837 Lang::Variable { name, .. } => assert_eq!(name, "x"),
1838 other => panic!("Expected Variable identifier, got {:?}", other),
1839 },
1840 other => panic!("Expected Assign, got {:?}", other),
1841 }
1842 }
1843
1844 #[test]
1845 fn test_implicit_mutate_ufc_pipeline() {
1846 let res = implicit_mutate("shape.scale(2) |> rotate(90)!;".into())
1847 .unwrap()
1848 .1;
1849 assert_eq!(res.len(), 1);
1850 match &res[0] {
1851 Lang::Assign { identifier, .. } => match identifier.as_ref() {
1852 Lang::Variable { name, .. } => assert_eq!(name, "shape"),
1853 other => panic!("Expected Variable identifier, got {:?}", other),
1854 },
1855 other => panic!("Expected Assign, got {:?}", other),
1856 }
1857 }
1858
1859 #[test]
1860 fn test_implicit_mutate_invalid_literal_fails() {
1861 let res = implicit_mutate("3!;".into());
1863 assert!(res.is_err(), "Literal mutation should fail to parse");
1864 }
1865}