1use crate::err::{Error, ErrorKind};
7use crate::{Analyzer, SPARSE_TYPE_ID, TypeContext};
8use swamp_script_semantic::Expression;
9use swamp_script_semantic::prelude::IntrinsicFunction;
10use swamp_script_semantic::{Postfix, PostfixKind};
11use swamp_script_types::prelude::*;
12
13impl Analyzer<'_> {
14 pub(crate) fn check_for_internal_member_call(
15 &mut self,
16 ty: &Type,
17 is_mutable: bool,
18 ast_member_function_name: &swamp_script_ast::Node,
19 ast_arguments: &[&swamp_script_ast::Expression],
20 ) -> Result<Option<Postfix>, Error> {
21 match &ty {
22 Type::Vec(array_type_ref) => {
23 let resolved = self.analyze_array_member_call(
24 array_type_ref,
25 is_mutable,
26 ast_member_function_name,
27 ast_arguments,
28 )?;
29 Ok(Some(resolved))
30 }
31
32 Type::Map(key, value) => {
33 let resolved = self.analyze_map_member_call(
34 key,
35 value,
36 is_mutable,
37 ast_member_function_name,
38 ast_arguments,
39 )?;
40 Ok(Some(resolved))
41 }
42
43 Type::Float => {
44 let resolved =
45 self.analyze_float_member_call(ast_member_function_name, ast_arguments)?;
46 Ok(Some(resolved))
47 }
48 Type::Int => {
49 let resolved =
50 self.analyze_int_member_call(ast_member_function_name, ast_arguments)?;
51 Ok(Some(resolved))
52 }
53 Type::String => {
54 let resolved =
55 self.analyze_string_member_call(ast_member_function_name, ast_arguments)?;
56 Ok(Some(resolved))
57 }
58 Type::Tuple(tuple_type) => {
59 let found = self.analyze_tuple_member_call(
60 tuple_type,
61 ast_member_function_name,
62 ast_arguments,
63 )?;
64 Ok(Some(found))
65 }
66 _ => self.check_for_internal_member_call_extra(
67 ty,
68 ast_member_function_name,
69 ast_arguments,
70 ),
71 }
72 }
73 fn analyze_tuple_member_call(
74 &mut self,
75 tuple_type: &[Type],
76 ast_member_function_name: &swamp_script_ast::Node,
77 arguments: &[&swamp_script_ast::Expression],
78 ) -> Result<Postfix, Error> {
79 if tuple_type.len() != 2 {
80 return Err(self.create_err(
81 ErrorKind::WrongNumberOfArguments(2, tuple_type.len()),
82 ast_member_function_name,
83 ));
84 }
85
86 let member_function_name_str = self.get_text(ast_member_function_name);
87
88 let resolved_expr = match (&tuple_type[0], &tuple_type[1]) {
89 (Type::Float, Type::Float) => match member_function_name_str {
90 "magnitude" => {
91 if !arguments.is_empty() {
92 return Err(self.create_err(
93 ErrorKind::WrongNumberOfArguments(arguments.len(), 0),
94 ast_member_function_name,
95 ));
96 }
97 self.create_postfix(
98 PostfixKind::IntrinsicCall(IntrinsicFunction::Float2Magnitude, vec![]),
99 &Type::Float,
100 ast_member_function_name,
101 )
102 }
103 _ => {
104 return Err(
105 self.create_err(ErrorKind::UnknownMemberFunction, ast_member_function_name)
106 );
107 }
108 },
109 _ => {
110 return Err(self.create_err(
111 ErrorKind::WrongNumberOfArguments(99, tuple_type.len()),
112 ast_member_function_name,
113 ));
114 }
115 };
116
117 Ok(resolved_expr)
118 }
119
120 fn check_mutable(
121 &mut self,
122 is_mutable: bool,
123 node: &swamp_script_ast::Node,
124 ) -> Result<(), Error> {
125 if is_mutable {
126 Ok(())
127 } else {
128 Err(self.create_err(ErrorKind::ExpectedMutableLocation, node))
129 }
130 }
131
132 fn create_postfix(
133 &mut self,
134 kind: PostfixKind,
135 ty: &Type,
136 node: &swamp_script_ast::Node,
137 ) -> Postfix {
138 let resolved_node = self.to_node(node);
139
140 Postfix {
141 node: resolved_node,
142 ty: ty.clone(),
143 kind,
144 }
145 }
146
147 fn analyze_map_member_call(
148 &mut self,
149 key_type: &Type,
150 _value_type: &Type,
151 is_mutable: bool,
152 ast_member_function_name: &swamp_script_ast::Node,
153 ast_arguments: &[&swamp_script_ast::Expression],
154 ) -> Result<Postfix, Error> {
155 let member_function_name_str = self.get_text(ast_member_function_name);
156 let key_arg_context = TypeContext::new_argument(&key_type);
157 let expr = match member_function_name_str {
158 "remove" => {
159 self.check_mutable(is_mutable, ast_member_function_name)?;
160
161 if ast_arguments.len() != 1 {
162 return Err(self.create_err(
163 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 1),
164 ast_member_function_name,
165 ));
166 }
167
168 let key_expr = self.analyze_expression(ast_arguments[0], &key_arg_context)?;
169
170 self.create_postfix(
171 PostfixKind::IntrinsicCall(IntrinsicFunction::MapRemove, vec![key_expr]),
172 &Type::Unit,
173 ast_member_function_name,
174 )
175 }
176
177 "has" => {
178 if ast_arguments.len() != 1 {
179 return Err(self.create_err(
180 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 1),
181 ast_member_function_name,
182 ));
183 }
184
185 let key_expr = self.analyze_expression(ast_arguments[0], &key_arg_context)?;
186
187 self.create_postfix(
188 PostfixKind::IntrinsicCall(IntrinsicFunction::MapHas, vec![key_expr]),
189 &Type::Bool,
190 ast_member_function_name,
191 )
192 }
193 _ => {
194 return Err(
195 self.create_err(ErrorKind::UnknownMemberFunction, ast_member_function_name)
196 );
197 }
198 };
199 Ok(expr)
200 }
201
202 fn analyze_array_member_call(
203 &mut self,
204 array_type_ref: &Type,
205 is_mutable: bool,
206 ast_member_function_name: &swamp_script_ast::Node,
207 ast_arguments: &[&swamp_script_ast::Expression],
208 ) -> Result<Postfix, Error> {
209 let member_function_name_str = self.get_text(ast_member_function_name);
210 let resolved_postfix = match member_function_name_str {
211 "remove" => {
212 self.check_mutable(is_mutable, ast_member_function_name)?;
213
214 if ast_arguments.len() != 1 {
215 return Err(self.create_err(
216 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 1),
217 ast_member_function_name,
218 ));
219 }
220 let index_expr = self.analyze_usize_index(ast_arguments[0])?;
221
222 self.create_postfix(
223 PostfixKind::IntrinsicCall(IntrinsicFunction::VecRemoveIndex, vec![index_expr]),
224 &Type::Unit,
225 ast_member_function_name,
226 )
227 }
228
229 "push" => {
230 self.check_mutable(is_mutable, ast_member_function_name)?;
231
232 if ast_arguments.len() != 1 {
233 return Err(self.create_err(
234 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 1),
235 ast_member_function_name,
236 ));
237 }
238
239 let element_type_context = TypeContext::new_argument(&array_type_ref);
240 let value_expr =
241 self.analyze_expression(ast_arguments[0], &element_type_context)?;
242
243 self.create_postfix(
244 PostfixKind::IntrinsicCall(IntrinsicFunction::VecPush, vec![value_expr]),
245 &Type::Unit,
246 ast_member_function_name,
247 )
248 }
249
250 "pop" => {
251 self.check_mutable(is_mutable, ast_member_function_name)?;
252
253 if ast_arguments.len() != 0 {
254 return Err(self.create_err(
255 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
256 ast_member_function_name,
257 ));
258 }
259
260 self.create_postfix(
261 PostfixKind::IntrinsicCall(IntrinsicFunction::VecPop, vec![]),
262 &Type::Optional(Box::from(array_type_ref.clone())),
263 ast_member_function_name,
264 )
265 }
266
267 "clear" => {
268 self.check_mutable(is_mutable, ast_member_function_name)?;
269
270 if !ast_arguments.is_empty() {
271 return Err(self.create_err(
272 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
273 ast_member_function_name,
274 ));
275 }
276
277 self.create_postfix(
278 PostfixKind::IntrinsicCall(IntrinsicFunction::VecClear, vec![]),
279 &Type::Unit,
280 ast_member_function_name,
281 )
282 }
283
284 "len" => {
285 if !ast_arguments.is_empty() {
286 return Err(self.create_err(
287 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
288 ast_member_function_name,
289 ));
290 }
291
292 self.create_postfix(
293 PostfixKind::IntrinsicCall(IntrinsicFunction::VecLen, vec![]),
294 &Type::Int,
295 ast_member_function_name,
296 )
297 }
298
299 "is_empty" => {
300 if !ast_arguments.is_empty() {
301 return Err(self.create_err(
302 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
303 ast_member_function_name,
304 ));
305 }
306
307 self.create_postfix(
308 PostfixKind::IntrinsicCall(IntrinsicFunction::VecIsEmpty, vec![]),
309 &Type::Bool,
310 ast_member_function_name,
311 )
312 }
313
314 _ => {
315 return Err(
316 self.create_err(ErrorKind::UnknownMemberFunction, &ast_member_function_name)
317 );
318 }
319 };
320
321 Ok(resolved_postfix)
322 }
323
324 fn analyze_single_float_expression(
325 &mut self,
326 node: &swamp_script_ast::Node,
327 ast_arguments: &[&swamp_script_ast::Expression],
328 ) -> Result<Expression, Error> {
329 if ast_arguments.len() != 1 {
330 return Err(self.create_err(
331 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 1),
332 node,
333 ));
334 }
335 let float_expression = { self.analyze_immutable_argument(ast_arguments[0], &Type::Float)? };
336
337 Ok(float_expression)
338 }
339
340 fn analyze_single_int_expression(
341 &mut self,
342 node: &swamp_script_ast::Node,
343 ast_arguments: &[&swamp_script_ast::Expression],
344 ) -> Result<Expression, Error> {
345 if ast_arguments.len() != 1 {
346 return Err(self.create_err(
347 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 1),
348 &node,
349 ));
350 }
351 let expr2 = self.analyze_immutable_argument(ast_arguments[0], &Type::Int)?;
352
353 Ok(expr2)
354 }
355
356 fn analyze_two_float_expressions(
357 &mut self,
358 node: &swamp_script_ast::Node,
359 ast_arguments: &[&swamp_script_ast::Expression],
360 ) -> Result<(Expression, Expression), Error> {
361 if ast_arguments.len() != 2 {
362 return Err(self.create_err(
363 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 2),
364 &node,
365 ));
366 }
367 let expr2 = self.analyze_immutable_argument(ast_arguments[0], &Type::Float)?;
368 let expr3 = self.analyze_immutable_argument(ast_arguments[1], &Type::Float)?;
369
370 Ok((expr2, expr3))
371 }
372
373 #[allow(clippy::too_many_lines)]
374 fn analyze_float_member_call(
375 &mut self,
376 ast_member_function_name: &swamp_script_ast::Node,
377 ast_arguments: &[&swamp_script_ast::Expression],
378 ) -> Result<Postfix, Error> {
379 let function_name_str = self.get_text(ast_member_function_name);
380 let node = ast_member_function_name;
381
382 let mut resulting_type = &Type::Float;
383 let kind = match function_name_str {
384 "round" => {
385 if !ast_arguments.is_empty() {
386 return Err(self.create_err(
387 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
388 ast_member_function_name,
389 ));
390 }
391 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatRound, vec![])
392 }
393 "floor" => {
394 if !ast_arguments.is_empty() {
395 return Err(self.create_err(
396 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
397 ast_member_function_name,
398 ));
399 }
400 resulting_type = &Type::Int;
401 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatFloor, vec![])
402 }
403 "sqrt" => {
404 if !ast_arguments.is_empty() {
405 return Err(self.create_err(
406 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
407 ast_member_function_name,
408 ));
409 }
410 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatSqrt, vec![])
411 }
412 "sign" => {
413 if !ast_arguments.is_empty() {
414 return Err(self.create_err(
415 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
416 ast_member_function_name,
417 ));
418 }
419 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatSign, vec![])
420 }
421 "abs" => {
422 if !ast_arguments.is_empty() {
423 return Err(self.create_err(
424 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
425 ast_member_function_name,
426 ));
427 }
428 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatAbs, vec![])
429 }
430 "rnd" => {
431 if !ast_arguments.is_empty() {
432 return Err(self.create_err(
433 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
434 ast_member_function_name,
435 ));
436 }
437 resulting_type = &Type::Int;
438 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatRnd, vec![])
439 }
440 "cos" => {
441 if !ast_arguments.is_empty() {
442 return Err(self.create_err(
443 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
444 ast_member_function_name,
445 ));
446 }
447 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatCos, vec![])
448 }
449 "sin" => {
450 if !ast_arguments.is_empty() {
451 return Err(self.create_err(
452 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
453 ast_member_function_name,
454 ));
455 }
456 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatSin, vec![])
457 }
458 "acos" => {
459 if !ast_arguments.is_empty() {
460 return Err(self.create_err(
461 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
462 ast_member_function_name,
463 ));
464 }
465 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatAcos, vec![])
466 }
467 "asin" => {
468 if !ast_arguments.is_empty() {
469 return Err(self.create_err(
470 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
471 ast_member_function_name,
472 ));
473 }
474 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatAsin, vec![])
475 }
476 "atan2" => {
477 let float_argument = self.analyze_single_float_expression(node, ast_arguments)?;
478 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatAtan2, vec![float_argument])
479 }
480 "min" => {
481 let float_argument = self.analyze_single_float_expression(node, ast_arguments)?;
482 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatMin, vec![float_argument])
483 }
484 "max" => {
485 let float_argument = self.analyze_single_float_expression(node, ast_arguments)?;
486 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatMax, vec![float_argument])
487 }
488 "clamp" => {
489 let (min, max) = self.analyze_two_float_expressions(node, ast_arguments)?;
490 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatClamp, vec![min, max])
491 }
492 _ => {
493 return Err(
494 self.create_err(ErrorKind::UnknownMemberFunction, ast_member_function_name)
495 );
496 }
497 };
498
499 Ok(self.create_postfix(kind, resulting_type, ast_member_function_name))
500 }
501
502 fn analyze_string_member_call(
503 &mut self,
504 ast_member_function_name: &swamp_script_ast::Node,
505 ast_arguments: &[&swamp_script_ast::Expression],
506 ) -> Result<Postfix, Error> {
507 let function_name_str = self.get_text(ast_member_function_name);
508 let node = self.to_node(ast_member_function_name);
509
510 match function_name_str {
511 "len" => {
512 if !ast_arguments.is_empty() {
513 return Err(self.create_err_resolved(
514 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
515 &node,
516 ));
517 }
518 Ok(self.create_postfix(
519 PostfixKind::IntrinsicCall(IntrinsicFunction::StringLen, vec![]),
520 &Type::Int,
521 ast_member_function_name,
522 ))
523 }
524 _ => Err(self.create_err(ErrorKind::UnknownMemberFunction, ast_member_function_name)),
525 }
526 }
527
528 fn analyze_int_member_call(
529 &mut self,
530 ast_member_function_name: &swamp_script_ast::Node,
531 ast_arguments: &[&swamp_script_ast::Expression],
532 ) -> Result<Postfix, Error> {
533 let function_name_str = self.get_text(ast_member_function_name);
534 let node = self.to_node(ast_member_function_name);
535
536 let (kind, resolved_type) = match function_name_str {
537 "abs" => {
538 if !ast_arguments.is_empty() {
539 return Err(self.create_err_resolved(
540 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
541 &node,
542 ));
543 }
544 (
545 PostfixKind::IntrinsicCall(IntrinsicFunction::IntAbs, vec![]),
546 Type::Int,
547 )
548 }
549 "rnd" => {
550 if !ast_arguments.is_empty() {
551 return Err(self.create_err_resolved(
552 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
553 &node,
554 ));
555 }
556 (
557 PostfixKind::IntrinsicCall(IntrinsicFunction::IntRnd, vec![]),
558 Type::Int,
559 )
560 }
561
562 "max" => {
563 let int_argument =
564 self.analyze_single_int_expression(ast_member_function_name, ast_arguments)?;
565 (
566 PostfixKind::IntrinsicCall(IntrinsicFunction::IntMax, vec![int_argument]),
567 Type::Int,
568 )
569 }
570
571 "min" => {
572 let int_argument =
573 self.analyze_single_int_expression(ast_member_function_name, ast_arguments)?;
574 (
575 PostfixKind::IntrinsicCall(IntrinsicFunction::IntMin, vec![int_argument]),
576 Type::Int,
577 )
578 }
579
580 "to_float" => {
581 if !ast_arguments.is_empty() {
582 return Err(self.create_err_resolved(
583 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
584 &node,
585 ));
586 }
587 (
588 PostfixKind::IntrinsicCall(IntrinsicFunction::IntToFloat, vec![]),
589 Type::Float,
590 )
591 }
592 _ => {
593 return Err(
594 self.create_err(ErrorKind::UnknownMemberFunction, ast_member_function_name)
595 );
596 }
597 };
598
599 Ok(self.create_postfix(kind, &resolved_type, ast_member_function_name))
600 }
601
602 fn check_for_internal_member_call_extra(
603 &mut self,
604 ty: &Type,
605 ast_member_function_name: &swamp_script_ast::Node,
606 ast_arguments: &[&swamp_script_ast::Expression],
607 ) -> Result<Option<Postfix>, Error> {
608 if let Type::Generic(generic_type, parameters) = ty.clone() {
610 if let Type::External(rust_type_ref) = *generic_type {
611 if rust_type_ref.as_ref().number == SPARSE_TYPE_ID {
612 if parameters.len() != 1 {
613 return Err(self.create_err(
614 ErrorKind::WrongNumberOfTypeArguments(parameters.len(), 1),
615 ast_member_function_name,
616 ));
617 }
618 let sparse_id_type = self
619 .shared
620 .lookup_table
621 .get_external_type("SparseId")
622 .expect("should have SparseId");
623 let key_type = Type::External(sparse_id_type.clone());
624 let value_type = ¶meters[0];
625 let function_name_str = self.get_text(ast_member_function_name);
626
627 let (kind, resolved_type) = match function_name_str {
629 "add" => {
630 if ast_arguments.len() != 1 {
631 return Err(self.create_err(
632 ErrorKind::WrongNumberOfTypeArguments(parameters.len(), 1),
633 ast_member_function_name,
634 ));
635 }
636 let value =
637 self.analyze_immutable_argument(&ast_arguments[0], value_type)?;
638 (
639 PostfixKind::IntrinsicCall(
640 IntrinsicFunction::SparseAdd,
641 vec![value],
642 ),
643 key_type,
644 )
645 }
646 "remove" => {
647 if ast_arguments.len() != 1 {
648 return Err(self.create_err(
649 ErrorKind::WrongNumberOfTypeArguments(parameters.len(), 1),
650 ast_member_function_name,
651 ));
652 }
653 let sparse_slot_id_expression =
654 self.analyze_immutable_argument(&ast_arguments[0], &key_type)?;
655 (
656 PostfixKind::IntrinsicCall(
657 IntrinsicFunction::SparseRemove,
658 vec![sparse_slot_id_expression],
659 ),
660 Type::Unit, )
662 }
663 _ => return Ok(None),
664 };
665
666 return Ok(Some(self.create_postfix(
667 kind,
668 &resolved_type,
669 ast_member_function_name,
670 )));
671 }
672 }
673 }
674
675 Ok(None)
676 }
677}