rl_lang/checker/scope/
call.rs1use crate::{
4 ast::statements::TypeAnnotation,
5 checker::structs::{CheckType, TypeChecker},
6 interpreter::stdlib,
7 utils::{span::Span, suggest::closest_match},
8};
9
10impl TypeChecker {
11 pub fn check_call_path(
22 &mut self,
23 path: &[String],
24 arg_types: &[(CheckType, Span)],
25 span: Span,
26 ) -> CheckType {
27 if self.root_module.resolve(path).is_some() {
29 self.push_stdlib_hover(path, span);
30 return CheckType::Unknown;
31 }
32
33 if path.len() == 1 {
34 let name = &path[0];
35
36 if self.stdlib_fn_names.contains(name.as_str()) {
37 self.push_stdlib_hover(path, span);
38 return CheckType::Unknown;
39 }
40 let item_type = self.lookup(name, span);
41 return self.check_call_value(item_type, arg_types, span);
42 }
43
44 let suggestion = if let Some(last) = path.last() {
45 let candidates = stdlib::math::KEYWORDS
46 .iter()
47 .chain(stdlib::math::constants::KEYWORDS)
48 .chain(stdlib::io::KEYWORDS)
49 .chain(stdlib::string::KEYWORDS)
50 .chain(stdlib::types::KEYWORDS)
51 .chain(stdlib::array::KEYWORDS)
52 .chain(stdlib::path::KEYWORDS)
53 .chain(stdlib::fs::KEYWORDS)
54 .copied();
55 closest_match(last, candidates)
56 } else {
57 None
58 };
59
60 self.error_with_help(
61 format!("undefined function {}", path.join("::")),
62 span,
63 suggestion,
64 );
65
66 CheckType::Unknown
67 }
68
69 pub fn check_call_value(
76 &mut self,
77 callee_type: CheckType,
78 arg_types: &[(CheckType, Span)],
79 span: Span,
80 ) -> CheckType {
81 match callee_type {
82 CheckType::Unknown => CheckType::Unknown,
83 CheckType::Known(TypeAnnotation::Fn) => CheckType::Unknown,
84 CheckType::Function {
85 params,
86 return_type,
87 } => {
88 if params.len() != arg_types.len() {
89 self.error(
90 format!(
91 "function expects {} argument(s), got {}",
92 params.len(),
93 arg_types.len()
94 ),
95 span,
96 );
97 return CheckType::Known(return_type);
98 }
99 for (expected_type, (actual_type, arg_span)) in params.iter().zip(arg_types.iter())
100 {
101 let expected = CheckType::Known(expected_type.clone());
102
103 if !actual_type.matches(&expected) {
104 self.error(
105 format!(
106 "type mismatch: expected {}, got {}",
107 expected.info(),
108 actual_type.info()
109 ),
110 *arg_span,
111 );
112 }
113 }
114 CheckType::Known(return_type)
115 }
116
117 other => {
118 self.error(format!("{} is not callable", other.info()), span);
119 CheckType::Unknown
120 }
121 }
122 }
123}