1use std::rc::Rc;
5
6use miette::Diagnostic;
7use petr_ast::{Ast, Commented, Expression, FunctionDeclaration, FunctionParameter, OperatorExpression};
8use petr_bind::{Binder, Dependency, FunctionId, Item, ScopeId};
9use petr_utils::{Identifier, Path, Span, SpannedItem, SymbolInterner, TypeId};
10use thiserror::Error;
11
12use crate::resolved::{QueryableResolvedItems, ResolvedItems};
13#[derive(Debug, Error, Diagnostic)]
14pub enum ResolutionError {
15 #[error("Function parameter not found: {0}")]
16 FunctionParameterNotFound(String),
17 #[error("Symbol not found: {0}")]
18 NotFound(String),
19 #[error("Could not find implementation for operator: {0} at {1}")]
20 OperatorImplementationNotFound(String, String),
21}
22
23pub(crate) struct Resolver {
24 pub resolved: ResolvedItems,
25 pub interner: SymbolInterner,
26 pub errs: Vec<SpannedItem<ResolutionError>>,
27}
28
29#[derive(Debug, Clone)]
30pub struct TypeDeclaration {
31 pub name: Identifier,
32 pub variants: Box<[TypeVariant]>,
33}
34
35#[derive(Debug, Clone)]
36pub struct TypeVariant {
37 pub name: Identifier,
38 pub fields: Box<[TypeField]>,
39}
40
41#[derive(Debug, Clone)]
42pub struct TypeField {
43 pub name: Identifier,
44 pub ty: Type,
45}
46
47#[derive(Clone, Copy, Debug)]
48pub enum Type {
49 Integer,
50 Bool,
51 Unit,
52 String,
53 ErrorRecovery,
55 Named(TypeId),
56 Generic(Identifier),
57}
58
59impl Resolve for petr_ast::Ty {
60 type Resolved = Type;
61
62 fn resolve(
63 &self,
64 _resolver: &mut Resolver,
65 binder: &Binder,
66 scope_id: ScopeId,
67 ) -> Option<Type> {
68 Some(match self {
69 petr_ast::Ty::Int => Type::Integer,
70 petr_ast::Ty::Bool => Type::Bool,
71 petr_ast::Ty::String => Type::String,
72 petr_ast::Ty::Unit => Type::Unit,
73 petr_ast::Ty::Named(name) => match binder.find_symbol_in_scope(name.id, scope_id) {
74 Some(Item::Type(id)) => Type::Named(*id),
75 Some(something) => {
76 let name = _resolver.interner.get(name.id);
77 todo!("push error -- symbol {name} is not type, it is a {something:?}");
82 },
84 None => Type::Generic(*name),
85 },
86 })
87 }
88}
89
90#[derive(Clone, Debug)]
91pub struct FunctionCall {
92 pub function: FunctionId,
93 pub args: Vec<Expr>,
94 pub span: Span,
95}
96
97impl FunctionCall {
98 pub fn span(&self) -> petr_utils::Span {
99 self.span
100 }
101}
102
103#[derive(Clone, Debug)]
104pub struct Function {
105 pub name: Identifier,
106 pub params: Vec<(Identifier, Type)>,
107 pub return_type: Type,
108 pub body: Expr,
109}
110
111#[derive(Clone, Debug)]
112pub struct Expr {
113 pub kind: ExprKind,
114 pub span: Span,
115}
116
117impl Expr {
118 pub fn error_recovery(span: Span) -> Self {
119 Self {
120 kind: ExprKind::ErrorRecovery,
121 span,
122 }
123 }
124
125 pub fn new(
126 kind: ExprKind,
127 span: Span,
128 ) -> Self {
129 Self { kind, span }
130 }
131}
132
133#[derive(Clone, Debug)]
134pub enum ExprKind {
135 Literal(petr_ast::Literal),
136 List(Box<[Expr]>),
137 FunctionCall(FunctionCall),
138 Variable { name: Identifier, ty: Type },
139 Intrinsic(Intrinsic),
140 Unit,
141 TypeConstructor(TypeId, Box<[Expr]>),
143 ErrorRecovery,
144 ExpressionWithBindings { bindings: Vec<Binding>, expression: Box<Expr> },
145}
146
147#[derive(Clone, Debug)]
148pub struct Binding {
149 pub name: Identifier,
150 pub expression: Expr,
151}
152
153#[derive(Clone, Debug)]
154pub struct Intrinsic {
155 pub intrinsic: petr_ast::Intrinsic,
156 pub args: Box<[Expr]>,
157}
158
159impl Resolver {
160 #[cfg(test)]
161 pub fn new_from_single_ast(
162 ast: Ast,
163 interner: SymbolInterner,
164 ) -> Self {
165 let binder = Binder::from_ast(&ast);
166 let mut resolver = Self {
167 errs: Vec::new(),
168 resolved: ResolvedItems::new(),
169 interner,
170 };
171 resolver.add_package(&binder);
172 resolver
173 }
174
175 pub fn new(
176 ast: Ast,
177 mut interner: SymbolInterner,
178 dependencies: Vec<Dependency>,
179 ) -> Self {
180 let binder = Binder::from_ast_and_deps(&ast, dependencies, &mut interner);
181 let mut resolver = Self {
182 errs: Vec::new(),
183 resolved: ResolvedItems::new(),
184 interner,
185 };
186 resolver.add_package(&binder);
187 resolver
188 }
189
190 pub fn add_package(
191 &mut self,
192 binder: &Binder,
193 ) {
194 let scopes_and_ids = binder.scope_iter().collect::<Vec<_>>();
196 for (scope_id, scope) in scopes_and_ids {
197 for (_name, item) in scope.iter() {
198 self.resolve_item(item.item(), binder, scope_id)
199 }
200 }
201 }
202
203 fn resolve_item(
204 &mut self,
205 item: &Item,
206 binder: &Binder,
207 scope_id: ScopeId,
208 ) {
209 use Item::*;
210 match item {
211 Function(func, func_scope) => self.resolve_function(binder, *func, *func_scope),
212 Type(ty) => self.resolve_type(binder, *ty, scope_id),
213 FunctionParameter(_ty) => {
214 },
216 Binding(a) => {
217 let binding = binder.get_binding(*a);
218 let resolved_expr = match binding.val.resolve(self, binder, scope_id) {
219 Some(o) => o,
220 None => {
221 let name = self.interner.get(binding.name.id);
222 self.errs.push(binding.name.span.with_item(ResolutionError::NotFound(name.to_string())));
223 return;
224 },
225 };
226 self.resolved.bindings.insert(
227 *a,
228 crate::resolver::Binding {
229 name: binding.name,
230 expression: resolved_expr,
231 },
232 );
233 },
234 Module(id) => {
236 let module = binder.get_module(*id);
237 let scope_id = module.root_scope;
238 let scope = binder.iter_scope(scope_id);
239 for (_name, item) in scope {
240 self.resolve_item(item.item(), binder, scope_id);
241 }
242 },
243 Import { .. } => { },
277 }
278 }
279
280 fn resolve_type(
281 &mut self,
282 binder: &Binder,
283 ty: TypeId,
284 scope_id: ScopeId,
285 ) {
286 let ty_decl = binder.get_type(ty).clone();
287 let Some(resolved) = ty_decl.resolve(self, binder, scope_id) else {
288 return;
289 };
290 self.resolved.insert_type(ty, resolved);
291 }
292
293 fn resolve_function(
294 &mut self,
295 binder: &Binder,
296 func_id: FunctionId,
297 scope_id: ScopeId,
298 ) {
299 let func = binder.get_function(func_id).clone();
305 let Some(func) = func.resolve(self, binder, scope_id) else {
306 return;
307 };
308 self.resolved.insert_function(func_id, func);
309 }
310
311 pub fn into_queryable(self) -> (Vec<SpannedItem<ResolutionError>>, QueryableResolvedItems) {
312 (
313 self.errs,
314 QueryableResolvedItems::new(self.resolved.resolved_functions, self.resolved.resolved_types, self.interner),
315 )
316 }
317}
318
319pub trait Resolve {
320 type Resolved;
321 fn resolve(
322 &self,
323 resolver: &mut Resolver,
324 binder: &Binder,
325 scope_id: ScopeId,
326 ) -> Option<Self::Resolved>;
327}
328
329impl Resolve for SpannedItem<FunctionDeclaration> {
330 type Resolved = Function;
331
332 fn resolve(
333 &self,
334 resolver: &mut Resolver,
335 binder: &Binder,
336 scope_id: ScopeId,
337 ) -> Option<Self::Resolved> {
338 let mut params_buf = Vec::with_capacity(self.item().parameters.len());
345
346 for FunctionParameter { name, ty } in self.item().parameters.iter() {
348 let ty = ty.resolve(resolver, binder, scope_id).unwrap_or(Type::Unit);
349 params_buf.push((*name, ty));
350 }
351
352 let return_type = self.item().return_type.resolve(resolver, binder, scope_id).unwrap_or(Type::Unit);
353
354 let body = match self.item().body.resolve(resolver, binder, scope_id) {
355 Some(x) => x,
356 None => Expr::error_recovery(self.span()),
361 };
362
363 Some(Function {
364 name: self.item().name,
365 params: params_buf,
366 return_type,
367 body,
368 })
369 }
370}
371
372impl Resolve for SpannedItem<Expression> {
373 type Resolved = Expr;
374
375 fn resolve(
376 &self,
377 resolver: &mut Resolver,
378 binder: &Binder,
379 scope_id: ScopeId,
380 ) -> Option<Expr> {
381 Some(match self.item() {
382 Expression::Literal(x) => Expr::new(ExprKind::Literal(x.clone()), self.span()),
383 Expression::List(list) => {
384 let list: Vec<Expr> = list
385 .elements
386 .iter()
387 .map(|x| match x.resolve(resolver, binder, scope_id) {
388 Some(x) => x,
389 None => todo!("error recovery"),
390 })
391 .collect();
392 Expr::new(ExprKind::List(list.into_boxed_slice()), self.span())
394 },
395 Expression::Operator(op) => {
396 let OperatorExpression { lhs, rhs, op } = *op.clone();
397 use petr_ast::Operator::*;
399 let func = match op.item() {
400 Plus => "add",
401 Minus => "sub",
402 Star => "mul",
403 Slash => "div",
404 };
405 let path = ["std", "ops", func];
406
407 let func_path = Path {
408 identifiers: path
409 .iter()
410 .map(|x| Identifier {
411 id: resolver.interner.insert(Rc::from(*x)),
412 span: self.span(),
413 })
414 .collect(),
415 };
416
417 let Some(either::Left(function)) = func_path.resolve(resolver, binder, scope_id) else {
418 resolver.errs.push(
419 self.span()
420 .with_item(ResolutionError::OperatorImplementationNotFound(func.to_string(), path.join("."))),
421 );
422 return None;
423 };
424
425 let call = FunctionCall {
426 function,
427 args: vec![lhs.resolve(resolver, binder, scope_id)?, rhs.resolve(resolver, binder, scope_id)?],
428 span: self.span(),
429 };
430
431 Expr::new(ExprKind::FunctionCall(call), self.span())
432 },
433 Expression::FunctionCall(decl) => {
434 let resolved_call = self.span().with_item(decl).resolve(resolver, binder, scope_id)?;
435
436 Expr::new(ExprKind::FunctionCall(resolved_call), self.span())
437 },
438 Expression::Variable(var) => {
439 let item = match binder.find_symbol_in_scope(var.id, scope_id) {
440 Some(item @ Item::FunctionParameter(_) | item @ Item::Binding(_)) => item,
441 _otherwise => {
442 let var_name = resolver.interner.get(var.id);
443 resolver.errs.push(var.span.with_item(ResolutionError::NotFound(var_name.to_string())));
444 return None;
445 },
446 };
447 match item {
448 Item::Binding(binding_id) => {
449 let binding = binder.get_binding(*binding_id);
450
451 Expr::new(
452 ExprKind::Variable {
453 name: *var,
454 ty: Type::Generic(binding.name),
457 },
458 self.span(),
459 )
460 },
461 Item::FunctionParameter(ty) => {
462 let ty = match ty.resolve(resolver, binder, scope_id) {
463 Some(ty) => ty,
464
465 None => {
466 todo!("not found err");
467 },
469 };
470
471 Expr::new(ExprKind::Variable { name: *var, ty }, self.span())
472 },
473 _ => unreachable!(),
474 }
475 },
476 Expression::TypeConstructor(parent_type_id, args) => {
477 let resolved_args = args
482 .iter()
483 .map(|x| match x.resolve(resolver, binder, scope_id) {
484 Some(x) => x,
485 None => todo!("error recov"),
486 })
487 .collect::<Vec<_>>();
488 Expr::new(ExprKind::TypeConstructor(*parent_type_id, resolved_args.into_boxed_slice()), self.span())
489 },
490 Expression::IntrinsicCall(intrinsic) => {
491 let resolved = intrinsic.resolve(resolver, binder, scope_id)?;
492 Expr::new(ExprKind::Intrinsic(resolved), self.span())
493 },
494 Expression::Binding(bound_expression) => {
495 let scope_id = binder.get_expr_scope(bound_expression.expr_id).expect("invariant: scope should exist");
496 let mut bindings: Vec<Binding> = Vec::with_capacity(bound_expression.bindings.len());
497 for binding in &bound_expression.bindings {
498 let rhs = binding.val.resolve(resolver, binder, scope_id)?;
499 bindings.push(Binding {
500 name: binding.name,
501 expression: rhs,
502 });
503 }
504 let expression = bound_expression.expression.resolve(resolver, binder, scope_id)?;
505 Expr::new(
506 ExprKind::ExpressionWithBindings {
507 expression: Box::new(expression),
508 bindings,
509 },
510 self.span(),
511 )
512 },
513 })
514 }
515}
516
517impl Resolve for petr_ast::IntrinsicCall {
518 type Resolved = Intrinsic;
519
520 fn resolve(
521 &self,
522 resolver: &mut Resolver,
523 binder: &Binder,
524 scope_id: ScopeId,
525 ) -> Option<Self::Resolved> {
526 let args = self
527 .args
528 .iter()
529 .map(|x| match x.resolve(resolver, binder, scope_id) {
530 Some(x) => x,
531 None => Expr::error_recovery(x.span()),
532 })
533 .collect();
534 Some(Intrinsic {
535 intrinsic: self.intrinsic.clone(),
536 args,
537 })
538 }
539}
540
541impl<T: Resolve> Resolve for Commented<T> {
542 type Resolved = T::Resolved;
543
544 fn resolve(
545 &self,
546 resolver: &mut Resolver,
547 binder: &Binder,
548 scope_id: ScopeId,
549 ) -> Option<Self::Resolved> {
550 self.item().resolve(resolver, binder, scope_id)
551 }
552}
553
554impl<T: Resolve> Resolve for SpannedItem<T> {
555 type Resolved = T::Resolved;
556
557 fn resolve(
558 &self,
559 resolver: &mut Resolver,
560 binder: &Binder,
561 scope_id: ScopeId,
562 ) -> Option<Self::Resolved> {
563 self.item().resolve(resolver, binder, scope_id)
564 }
565}
566
567impl Resolve for SpannedItem<&petr_ast::FunctionCall> {
568 type Resolved = FunctionCall;
569
570 fn resolve(
571 &self,
572 resolver: &mut Resolver,
573 binder: &Binder,
574 scope_id: ScopeId,
575 ) -> Option<Self::Resolved> {
576 let resolved_id = match self.item().func_name.resolve(resolver, binder, scope_id) {
577 Some(either::Either::Left(func)) => func,
578 Some(either::Either::Right(_ty)) => {
579 todo!("push error -- tried to call ty as func");
580 },
581 None => {
582 let stringified_name = self
583 .item()
584 .func_name
585 .identifiers
586 .iter()
587 .map(|x| resolver.interner.get(x.id))
588 .collect::<Vec<_>>()
589 .join(".");
590 resolver.errs.push(self.span().with_item(ResolutionError::NotFound(stringified_name)));
591 return None;
592 },
593 };
594
595 let args = self
596 .item()
597 .args
598 .iter()
599 .map(|x| match x.resolve(resolver, binder, scope_id) {
600 Some(x) => x,
601 None => todo!("Error recov"),
602 })
603 .collect();
604
605 Some(FunctionCall {
606 function: resolved_id,
607 args,
608 span: self.span(),
609 })
610 }
611}
612
613impl Resolve for petr_utils::Path {
614 type Resolved = either::Either<FunctionId, TypeId>;
616
617 fn resolve(
618 &self,
619 resolver: &mut Resolver,
620 binder: &Binder,
621 scope_id: ScopeId,
622 ) -> Option<Self::Resolved> {
623 let mut path_iter = self.identifiers.iter();
624 let Some(first_item) = ({
625 let item = path_iter.next().expect("import with no items was parsed -- should be an invariant");
626 binder.find_symbol_in_scope(item.id, scope_id)
627 }) else {
628 let name = self.identifiers.iter().map(|x| resolver.interner.get(x.id)).collect::<Vec<_>>().join(".");
629 resolver.errs.push(
630 self.identifiers
631 .last()
632 .expect("empty path shouldn't be possible")
633 .span
634 .with_item(ResolutionError::NotFound(name)),
635 );
636 return None;
637 };
638
639 let first_item = match first_item {
640 Item::Module(id) if self.identifiers.len() > 1 => id,
641 Item::Function(f, _) if self.identifiers.len() == 1 => return Some(either::Either::Left(*f)),
642 Item::Type(t) if self.identifiers.len() == 1 => return Some(either::Either::Right(*t)),
643 Item::Import { path, alias: _ } if self.identifiers.len() == 1 => return path.resolve(resolver, binder, scope_id),
644 a => todo!("push error -- import path is not a module {a:?}"),
645 };
646
647 let mut rover = binder.get_module(*first_item);
648 for (ix, item) in path_iter.enumerate() {
650 let is_last = ix == self.identifiers.len() - 2; let Some(next_symbol) = binder.find_symbol_in_scope(item.id, rover.root_scope) else {
652 let name = resolver.interner.get(item.id);
653 resolver.errs.push(item.span.with_item(ResolutionError::NotFound(name.to_string())));
654 return None;
655 };
656
657 match next_symbol {
658 Item::Module(id) => rover = binder.get_module(*id),
659 Item::Function(func, _scope) if is_last => return Some(either::Either::Left(*func)),
660 Item::Type(ty) if is_last => return Some(either::Either::Right(*ty)),
661 Item::Import { path, alias: _ } => match path.resolve(resolver, binder, scope_id) {
662 Some(either::Left(func)) => return Some(either::Left(func)),
663 Some(either::Right(ty)) => return Some(either::Right(ty)),
664 None => todo!("push error -- import not found"),
665 },
666 a => todo!("push error -- import path item is not a module, it is a {a:?}"),
667 }
668 }
669
670 todo!("import of module not supported yet, must be type or function")
671 }
672}
673
674impl Resolve for petr_ast::TypeDeclaration {
675 type Resolved = TypeDeclaration;
676
677 fn resolve(
678 &self,
679 resolver: &mut Resolver,
680 binder: &Binder,
681 scope_id: ScopeId,
682 ) -> Option<Self::Resolved> {
683 let mut variants = Vec::with_capacity(self.variants.len());
690 for variant in self.variants.iter() {
691 let mut field_types = Vec::with_capacity(variant.item().fields.len());
692 for field in variant.item().fields.iter() {
693 if let Some(field_type) = field.item().ty.resolve(resolver, binder, scope_id) {
694 field_types.push(TypeField {
695 name: field.item().name,
696 ty: field_type,
697 });
698 } else {
699 return None;
701 }
702 }
703 variants.push(TypeVariant {
704 name: variant.item().name,
705 fields: field_types.into_boxed_slice(),
706 });
707 }
708
709 Some(TypeDeclaration {
710 name: self.name,
711 variants: variants.into_boxed_slice(),
712 })
713 }
714}
715
716#[cfg(test)]
717mod tests {
718 mod pretty_printing {
719
720 use super::{Expr, ExprKind};
721 use crate::{resolved::QueryableResolvedItems, resolver::Type};
722 impl Expr {
723 pub fn to_string(
724 &self,
725 resolver: &QueryableResolvedItems,
726 ) -> String {
727 self.kind.to_string(resolver)
728 }
729 }
730
731 impl Type {
732 pub fn to_string(
733 &self,
734 resolver: &QueryableResolvedItems,
735 ) -> String {
736 match self {
737 Type::Integer => "int".to_string(),
738 Type::Bool => "bool".to_string(),
739 Type::Unit => "()".to_string(),
740 Type::String => "string".to_string(),
741 Type::ErrorRecovery => "<error>".to_string(),
742 Type::Named(id) => {
743 format!("named type {}", resolver.interner.get(resolver.get_type(*id).name.id))
744 },
745 Type::Generic(a) => format!("generic type {}", resolver.interner.get(a.id)),
746 }
747 }
748 }
749
750 impl ExprKind {
751 pub fn to_string(
752 &self,
753 resolver: &QueryableResolvedItems,
754 ) -> String {
755 match self {
756 ExprKind::Literal(lit) => format!("Literal({:?})", lit),
757 ExprKind::List(exprs) => format!("[{}]", exprs.iter().map(|x| x.to_string(resolver)).collect::<Vec<_>>().join(", ")),
758 ExprKind::FunctionCall(call) => {
759 format!("FunctionCall({})", call.function)
760 },
761 ExprKind::Unit => "Unit".to_string(),
762 ExprKind::ErrorRecovery => "<error>".to_string(),
763 ExprKind::Variable { name, ty } => format!("{}: {}", resolver.interner.get(name.id), ty.to_string(resolver)),
764 ExprKind::Intrinsic(x) => format!(
765 "@{}({})",
766 x.intrinsic,
767 x.args.iter().map(|x| x.to_string(resolver)).collect::<Vec<_>>().join(", ")
768 ),
769 ExprKind::TypeConstructor(..) => "Type constructor".into(),
770 ExprKind::ExpressionWithBindings { .. } => todo!(),
771 }
772 }
773 }
774 }
775 use expect_test::{expect, Expect};
776 use petr_utils::render_error;
777
778 use super::*;
779 use crate::resolved::QueryableResolvedItems;
780 fn check(
781 input: impl Into<String>,
782 expect: Expect,
783 ) {
784 let input = input.into();
785 let parser = petr_parse::Parser::new(vec![("test", input)]);
786 let (ast, errs, interner, source_map) = parser.into_result();
787 if !errs.is_empty() {
788 errs.into_iter().for_each(|err| eprintln!("{:?}", render_error(&source_map, err)));
789 panic!("fmt failed: code didn't parse");
790 }
791 let resolver = Resolver::new_from_single_ast(ast, interner);
792 let (errs, queryable) = resolver.into_queryable();
793 assert!(errs.is_empty());
794 let result = pretty_print_resolution(&queryable);
795 expect.assert_eq(&result);
796 }
797
798 fn check_multiple(
799 inputs: Vec<impl Into<String>>,
800 expect: Expect,
801 ) {
802 let inputs: Vec<_> = inputs
803 .into_iter()
804 .enumerate()
805 .map(|(i, input)| (format!("test{}", i + 1), input.into()))
806 .collect();
807 let parser = petr_parse::Parser::new(inputs);
808 let (ast, errs, interner, source_map) = parser.into_result();
809 if !errs.is_empty() {
810 errs.into_iter().for_each(|err| eprintln!("{:?}", render_error(&source_map, err)));
811 panic!("fmt failed: code didn't parse");
812 }
813 let resolver = Resolver::new_from_single_ast(ast, interner);
814 let (errs, queryable) = resolver.into_queryable();
815 assert!(errs.is_empty());
816 let result = pretty_print_resolution(&queryable);
817 expect.assert_eq(&result);
818 }
819
820 fn pretty_print_resolution(queryable: &QueryableResolvedItems) -> String {
821 let mut result = String::new();
822 result.push_str("_____FUNCTIONS_____\n");
823 for (func_id, func) in queryable.functions() {
824 result.push_str(&format!("#{} {}", Into::<usize>::into(func_id), queryable.interner.get(func.name.id),));
825 result.push('(');
826 for (name, ty) in &func.params {
827 let name = queryable.interner.get(name.id);
828 let ty = ty.to_string(queryable);
829 result.push_str(&format!(" {}: {}, ", name, ty));
830 }
831 result.push_str(") ");
832 let ty = func.return_type.to_string(queryable);
833 result.push_str(&format!("-> {} ", ty));
834 result.push_str(&format!(" {:?}\n", func.body.to_string(queryable)));
835 }
836
837 result.push_str("_____TYPES_____\n");
838 for (type_id, ty_decl) in queryable.types() {
839 result.push_str(&format!("#{} {}", Into::<usize>::into(type_id), queryable.interner.get(ty_decl.name.id),));
840 result.push_str("\n\n");
841 }
842
843 result
844 }
845
846 #[test]
847 fn func_returns_list() {
848 check(
849 r#"
850 fn foo(a in 'int) returns 'int [1, 2, 3]
851 "#,
852 expect![[r#"
853 _____FUNCTIONS_____
854 #0 foo( a: int, ) -> int "[Literal(Integer(1)), Literal(Integer(2)), Literal(Integer(3))]"
855 _____TYPES_____
856 "#]],
857 );
858 }
859 #[test]
860 fn func_returns_named_type() {
861 check(
862 r#"
863 type MyType = a | b
864 fn foo(a in 'MyType) returns 'MyType [1, 2, 3]
865 "#,
866 expect![[r#"
867 _____FUNCTIONS_____
868 #0 a() -> named type MyType "Type constructor"
869 #1 b() -> named type MyType "Type constructor"
870 #2 foo( a: named type MyType, ) -> named type MyType "[Literal(Integer(1)), Literal(Integer(2)), Literal(Integer(3))]"
871 _____TYPES_____
872 #0 MyType
873
874 "#]],
875 );
876 }
877
878 #[test]
879 fn func_returns_named_type_declared_after_use() {
880 check(
881 r#"
882 fn foo(a in 'MyType) returns 'MyType [
883 1,
884 2,
885 3
886 ]
887 type MyType = a | b
888 "#,
889 expect![[r#"
890 _____FUNCTIONS_____
891 #0 foo( a: named type MyType, ) -> named type MyType "[Literal(Integer(1)), Literal(Integer(2)), Literal(Integer(3))]"
892 #1 a() -> named type MyType "Type constructor"
893 #2 b() -> named type MyType "Type constructor"
894 _____TYPES_____
895 #0 MyType
896
897 "#]],
898 )
899 }
900
901 #[test]
902 fn call_func_before_decl() {
903 check(
904 r#"
905 fn foo() returns 'MyType ~bar(5)
906 fn bar(a in 'MyType) returns 'MyType [
907 1,
908 2,
909 3
910 ]
911 type MyType = a | b
912 "#,
913 expect![[r#"
914 _____FUNCTIONS_____
915 #0 foo() -> named type MyType "FunctionCall(functionid1)"
916 #1 bar( a: named type MyType, ) -> named type MyType "[Literal(Integer(1)), Literal(Integer(2)), Literal(Integer(3))]"
917 #2 a() -> named type MyType "Type constructor"
918 #3 b() -> named type MyType "Type constructor"
919 _____TYPES_____
920 #0 MyType
921
922 "#]],
923 )
924 }
925
926 #[test]
927 fn call_func_in_list_before_decl() {
928 check(
929 r#"
930 fn foo() returns 'MyType ~bar(5)
931 fn bar(a in 'MyType) returns 'MyType [
932 1,
933 2,
934 3
935 ]
936 type MyType = a | b
937 "#,
938 expect![[r#"
939 _____FUNCTIONS_____
940 #0 foo() -> named type MyType "FunctionCall(functionid1)"
941 #1 bar( a: named type MyType, ) -> named type MyType "[Literal(Integer(1)), Literal(Integer(2)), Literal(Integer(3))]"
942 #2 a() -> named type MyType "Type constructor"
943 #3 b() -> named type MyType "Type constructor"
944 _____TYPES_____
945 #0 MyType
946
947 "#]],
948 )
949 }
950 #[test]
951 fn import_something_from_another_file() {
952 check_multiple(
953 vec![
954 r#"
955 export fn exported_func(a in 'int) returns 'int a
956 "#,
957 r#"
958 import test1.exported_func
959
960 fn foo() returns 'int ~exported_func(5)
961
962 "#,
963 ],
964 expect![[r#"
965 _____FUNCTIONS_____
966 #0 exported_func( a: int, ) -> int "a: int"
967 #1 foo() -> int "FunctionCall(functionid0)"
968 _____TYPES_____
969 "#]],
970 )
971 }
972
973 #[test]
974 fn import_something_from_another_file_with_alias() {
975 check_multiple(
976 vec![
977 r#"
978 export fn exported_func(a in 'int) returns 'int a
979 "#,
980 r#"
981 import test1.exported_func as bar
982
983 fn foo() returns 'int ~bar(5)
984
985 "#,
986 ],
987 expect![[r#"
988 _____FUNCTIONS_____
989 #0 exported_func( a: int, ) -> int "a: int"
990 #1 foo() -> int "FunctionCall(functionid0)"
991 _____TYPES_____
992 "#]],
993 )
994 }
995}