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 "len" => {
178 if ast_arguments.len() != 0 {
181 return Err(self.create_err(
182 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
183 ast_member_function_name,
184 ));
185 }
186
187 self.create_postfix(
188 PostfixKind::IntrinsicCall(IntrinsicFunction::MapLen, vec![]),
189 &Type::Int,
190 ast_member_function_name,
191 )
192 }
193
194 "has" => {
195 if ast_arguments.len() != 1 {
196 return Err(self.create_err(
197 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 1),
198 ast_member_function_name,
199 ));
200 }
201
202 let key_expr = self.analyze_expression(ast_arguments[0], &key_arg_context)?;
203
204 self.create_postfix(
205 PostfixKind::IntrinsicCall(IntrinsicFunction::MapHas, vec![key_expr]),
206 &Type::Bool,
207 ast_member_function_name,
208 )
209 }
210 _ => {
211 return Err(
212 self.create_err(ErrorKind::UnknownMemberFunction, ast_member_function_name)
213 );
214 }
215 };
216 Ok(expr)
217 }
218
219 fn analyze_array_member_call(
220 &mut self,
221 array_type_ref: &Type,
222 is_mutable: bool,
223 ast_member_function_name: &swamp_script_ast::Node,
224 ast_arguments: &[&swamp_script_ast::Expression],
225 ) -> Result<Postfix, Error> {
226 let member_function_name_str = self.get_text(ast_member_function_name);
227 let resolved_postfix = match member_function_name_str {
228 "remove" => {
229 self.check_mutable(is_mutable, ast_member_function_name)?;
230
231 if ast_arguments.len() != 1 {
232 return Err(self.create_err(
233 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 1),
234 ast_member_function_name,
235 ));
236 }
237 let index_expr = self.analyze_usize_index(ast_arguments[0])?;
238
239 self.create_postfix(
240 PostfixKind::IntrinsicCall(IntrinsicFunction::VecRemoveIndex, vec![index_expr]),
241 &Type::Unit,
242 ast_member_function_name,
243 )
244 }
245
246 "push" => {
247 self.check_mutable(is_mutable, ast_member_function_name)?;
248
249 if ast_arguments.len() != 1 {
250 return Err(self.create_err(
251 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 1),
252 ast_member_function_name,
253 ));
254 }
255
256 let element_type_context = TypeContext::new_argument(&array_type_ref);
257 let value_expr =
258 self.analyze_expression(ast_arguments[0], &element_type_context)?;
259
260 self.create_postfix(
261 PostfixKind::IntrinsicCall(IntrinsicFunction::VecPush, vec![value_expr]),
262 &Type::Unit,
263 ast_member_function_name,
264 )
265 }
266
267 "pop" => {
268 self.check_mutable(is_mutable, ast_member_function_name)?;
269
270 if ast_arguments.len() != 0 {
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::VecPop, vec![]),
279 &Type::Optional(Box::from(array_type_ref.clone())),
280 ast_member_function_name,
281 )
282 }
283
284 "clear" => {
285 self.check_mutable(is_mutable, ast_member_function_name)?;
286
287 if !ast_arguments.is_empty() {
288 return Err(self.create_err(
289 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
290 ast_member_function_name,
291 ));
292 }
293
294 self.create_postfix(
295 PostfixKind::IntrinsicCall(IntrinsicFunction::VecClear, vec![]),
296 &Type::Unit,
297 ast_member_function_name,
298 )
299 }
300
301 "len" => {
302 if !ast_arguments.is_empty() {
303 return Err(self.create_err(
304 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
305 ast_member_function_name,
306 ));
307 }
308
309 self.create_postfix(
310 PostfixKind::IntrinsicCall(IntrinsicFunction::VecLen, vec![]),
311 &Type::Int,
312 ast_member_function_name,
313 )
314 }
315
316 "is_empty" => {
317 if !ast_arguments.is_empty() {
318 return Err(self.create_err(
319 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
320 ast_member_function_name,
321 ));
322 }
323
324 self.create_postfix(
325 PostfixKind::IntrinsicCall(IntrinsicFunction::VecIsEmpty, vec![]),
326 &Type::Bool,
327 ast_member_function_name,
328 )
329 }
330
331 _ => {
332 return Err(
333 self.create_err(ErrorKind::UnknownMemberFunction, &ast_member_function_name)
334 );
335 }
336 };
337
338 Ok(resolved_postfix)
339 }
340
341 fn analyze_single_float_expression(
342 &mut self,
343 node: &swamp_script_ast::Node,
344 ast_arguments: &[&swamp_script_ast::Expression],
345 ) -> Result<Expression, Error> {
346 if ast_arguments.len() != 1 {
347 return Err(self.create_err(
348 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 1),
349 node,
350 ));
351 }
352 let float_expression = { self.analyze_immutable_argument(ast_arguments[0], &Type::Float)? };
353
354 Ok(float_expression)
355 }
356
357 fn analyze_single_int_expression(
358 &mut self,
359 node: &swamp_script_ast::Node,
360 ast_arguments: &[&swamp_script_ast::Expression],
361 ) -> Result<Expression, Error> {
362 if ast_arguments.len() != 1 {
363 return Err(self.create_err(
364 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 1),
365 &node,
366 ));
367 }
368 let expr2 = self.analyze_immutable_argument(ast_arguments[0], &Type::Int)?;
369
370 Ok(expr2)
371 }
372
373 fn analyze_two_float_expressions(
374 &mut self,
375 node: &swamp_script_ast::Node,
376 ast_arguments: &[&swamp_script_ast::Expression],
377 ) -> Result<(Expression, Expression), Error> {
378 if ast_arguments.len() != 2 {
379 return Err(self.create_err(
380 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 2),
381 &node,
382 ));
383 }
384 let expr2 = self.analyze_immutable_argument(ast_arguments[0], &Type::Float)?;
385 let expr3 = self.analyze_immutable_argument(ast_arguments[1], &Type::Float)?;
386
387 Ok((expr2, expr3))
388 }
389
390 #[allow(clippy::too_many_lines)]
391 fn analyze_float_member_call(
392 &mut self,
393 ast_member_function_name: &swamp_script_ast::Node,
394 ast_arguments: &[&swamp_script_ast::Expression],
395 ) -> Result<Postfix, Error> {
396 let function_name_str = self.get_text(ast_member_function_name);
397 let node = ast_member_function_name;
398
399 let mut resulting_type = &Type::Float;
400 let kind = match function_name_str {
401 "round" => {
402 if !ast_arguments.is_empty() {
403 return Err(self.create_err(
404 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
405 ast_member_function_name,
406 ));
407 }
408 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatRound, vec![])
409 }
410 "floor" => {
411 if !ast_arguments.is_empty() {
412 return Err(self.create_err(
413 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
414 ast_member_function_name,
415 ));
416 }
417 resulting_type = &Type::Int;
418 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatFloor, vec![])
419 }
420 "sqrt" => {
421 if !ast_arguments.is_empty() {
422 return Err(self.create_err(
423 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
424 ast_member_function_name,
425 ));
426 }
427 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatSqrt, vec![])
428 }
429 "sign" => {
430 if !ast_arguments.is_empty() {
431 return Err(self.create_err(
432 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
433 ast_member_function_name,
434 ));
435 }
436 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatSign, vec![])
437 }
438 "abs" => {
439 if !ast_arguments.is_empty() {
440 return Err(self.create_err(
441 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
442 ast_member_function_name,
443 ));
444 }
445 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatAbs, vec![])
446 }
447 "rnd" => {
448 if !ast_arguments.is_empty() {
449 return Err(self.create_err(
450 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
451 ast_member_function_name,
452 ));
453 }
454 resulting_type = &Type::Int;
455 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatRnd, vec![])
456 }
457 "cos" => {
458 if !ast_arguments.is_empty() {
459 return Err(self.create_err(
460 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
461 ast_member_function_name,
462 ));
463 }
464 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatCos, vec![])
465 }
466 "sin" => {
467 if !ast_arguments.is_empty() {
468 return Err(self.create_err(
469 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
470 ast_member_function_name,
471 ));
472 }
473 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatSin, vec![])
474 }
475 "acos" => {
476 if !ast_arguments.is_empty() {
477 return Err(self.create_err(
478 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
479 ast_member_function_name,
480 ));
481 }
482 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatAcos, vec![])
483 }
484 "asin" => {
485 if !ast_arguments.is_empty() {
486 return Err(self.create_err(
487 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
488 ast_member_function_name,
489 ));
490 }
491 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatAsin, vec![])
492 }
493 "atan2" => {
494 let float_argument = self.analyze_single_float_expression(node, ast_arguments)?;
495 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatAtan2, vec![float_argument])
496 }
497 "min" => {
498 let float_argument = self.analyze_single_float_expression(node, ast_arguments)?;
499 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatMin, vec![float_argument])
500 }
501 "max" => {
502 let float_argument = self.analyze_single_float_expression(node, ast_arguments)?;
503 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatMax, vec![float_argument])
504 }
505 "clamp" => {
506 let (min, max) = self.analyze_two_float_expressions(node, ast_arguments)?;
507 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatClamp, vec![min, max])
508 }
509 _ => {
510 return Err(
511 self.create_err(ErrorKind::UnknownMemberFunction, ast_member_function_name)
512 );
513 }
514 };
515
516 Ok(self.create_postfix(kind, resulting_type, ast_member_function_name))
517 }
518
519 fn analyze_string_member_call(
520 &mut self,
521 ast_member_function_name: &swamp_script_ast::Node,
522 ast_arguments: &[&swamp_script_ast::Expression],
523 ) -> Result<Postfix, Error> {
524 let function_name_str = self.get_text(ast_member_function_name);
525 let node = self.to_node(ast_member_function_name);
526
527 match function_name_str {
528 "len" => {
529 if !ast_arguments.is_empty() {
530 return Err(self.create_err_resolved(
531 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
532 &node,
533 ));
534 }
535 Ok(self.create_postfix(
536 PostfixKind::IntrinsicCall(IntrinsicFunction::StringLen, vec![]),
537 &Type::Int,
538 ast_member_function_name,
539 ))
540 }
541 _ => Err(self.create_err(ErrorKind::UnknownMemberFunction, ast_member_function_name)),
542 }
543 }
544
545 fn analyze_int_member_call(
546 &mut self,
547 ast_member_function_name: &swamp_script_ast::Node,
548 ast_arguments: &[&swamp_script_ast::Expression],
549 ) -> Result<Postfix, Error> {
550 let function_name_str = self.get_text(ast_member_function_name);
551 let node = self.to_node(ast_member_function_name);
552
553 let (kind, resolved_type) = match function_name_str {
554 "abs" => {
555 if !ast_arguments.is_empty() {
556 return Err(self.create_err_resolved(
557 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
558 &node,
559 ));
560 }
561 (
562 PostfixKind::IntrinsicCall(IntrinsicFunction::IntAbs, vec![]),
563 Type::Int,
564 )
565 }
566 "rnd" => {
567 if !ast_arguments.is_empty() {
568 return Err(self.create_err_resolved(
569 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
570 &node,
571 ));
572 }
573 (
574 PostfixKind::IntrinsicCall(IntrinsicFunction::IntRnd, vec![]),
575 Type::Int,
576 )
577 }
578
579 "max" => {
580 let int_argument =
581 self.analyze_single_int_expression(ast_member_function_name, ast_arguments)?;
582 (
583 PostfixKind::IntrinsicCall(IntrinsicFunction::IntMax, vec![int_argument]),
584 Type::Int,
585 )
586 }
587
588 "min" => {
589 let int_argument =
590 self.analyze_single_int_expression(ast_member_function_name, ast_arguments)?;
591 (
592 PostfixKind::IntrinsicCall(IntrinsicFunction::IntMin, vec![int_argument]),
593 Type::Int,
594 )
595 }
596
597 "to_float" => {
598 if !ast_arguments.is_empty() {
599 return Err(self.create_err_resolved(
600 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
601 &node,
602 ));
603 }
604 (
605 PostfixKind::IntrinsicCall(IntrinsicFunction::IntToFloat, vec![]),
606 Type::Float,
607 )
608 }
609 _ => {
610 return Err(
611 self.create_err(ErrorKind::UnknownMemberFunction, ast_member_function_name)
612 );
613 }
614 };
615
616 Ok(self.create_postfix(kind, &resolved_type, ast_member_function_name))
617 }
618
619 fn check_for_internal_member_call_extra(
620 &mut self,
621 ty: &Type,
622 ast_member_function_name: &swamp_script_ast::Node,
623 ast_arguments: &[&swamp_script_ast::Expression],
624 ) -> Result<Option<Postfix>, Error> {
625 if let Type::Generic(generic_type, parameters) = ty.clone() {
627 if let Type::External(rust_type_ref) = *generic_type {
628 if rust_type_ref.as_ref().number == SPARSE_TYPE_ID {
629 if parameters.len() != 1 {
630 return Err(self.create_err(
631 ErrorKind::WrongNumberOfTypeArguments(parameters.len(), 1),
632 ast_member_function_name,
633 ));
634 }
635 let sparse_id_type = self
636 .shared
637 .lookup_table
638 .get_external_type("SparseId")
639 .expect("should have SparseId");
640 let key_type = Type::External(sparse_id_type.clone());
641 let value_type = ¶meters[0];
642 let function_name_str = self.get_text(ast_member_function_name);
643
644 let (kind, resolved_type) = match function_name_str {
646 "add" => {
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 value =
654 self.analyze_immutable_argument(&ast_arguments[0], value_type)?;
655 (
656 PostfixKind::IntrinsicCall(
657 IntrinsicFunction::SparseAdd,
658 vec![value],
659 ),
660 key_type,
661 )
662 }
663 "remove" => {
664 if ast_arguments.len() != 1 {
665 return Err(self.create_err(
666 ErrorKind::WrongNumberOfTypeArguments(parameters.len(), 1),
667 ast_member_function_name,
668 ));
669 }
670 let sparse_slot_id_expression =
671 self.analyze_immutable_argument(&ast_arguments[0], &key_type)?;
672 (
673 PostfixKind::IntrinsicCall(
674 IntrinsicFunction::SparseRemove,
675 vec![sparse_slot_id_expression],
676 ),
677 Type::Unit, )
679 }
680 _ => return Ok(None),
681 };
682
683 return Ok(Some(self.create_postfix(
684 kind,
685 &resolved_type,
686 ast_member_function_name,
687 )));
688 }
689 }
690 }
691
692 Ok(None)
693 }
694}