1use crate::err::{Error, ErrorKind};
7use crate::{Analyzer, SPARSE_TYPE_ID, TypeContext};
8use swamp_script_semantic::prelude::IntrinsicFunction;
9use swamp_script_semantic::{ArrayTypeRef, MapTypeRef, Postfix, PostfixKind, TupleTypeRef};
10use swamp_script_semantic::{Expression, Type};
11
12impl<'a> Analyzer<'a> {
13 pub(crate) fn check_for_internal_member_call(
14 &mut self,
15 ty: &Type,
16 is_mutable: bool,
17 ast_member_function_name: &swamp_script_ast::Node,
18 ast_arguments: &[&swamp_script_ast::Expression],
19 ) -> Result<Option<Postfix>, Error> {
20 match &ty {
21 Type::Array(array_type_ref) => {
22 let resolved = self.analyze_array_member_call(
23 array_type_ref,
24 is_mutable,
25 ast_member_function_name,
26 ast_arguments,
27 )?;
28 return Ok(Some(resolved));
29 }
30
31 Type::Map(map_type_ref) => {
32 let resolved = self.analyze_map_member_call(
34 &map_type_ref,
35 is_mutable,
36 ast_member_function_name,
37 ast_arguments,
38 )?;
39 Ok(Some(resolved))
40 }
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: &TupleTypeRef,
76 ast_member_function_name: &swamp_script_ast::Node,
77 arguments: &[&swamp_script_ast::Expression],
78 ) -> Result<Postfix, Error> {
79 if tuple_type.0.len() != 2 {
81 return Err(self.create_err(
82 ErrorKind::WrongNumberOfArguments(2, tuple_type.0.len()),
83 ast_member_function_name,
84 ));
85 }
86
87 let member_function_name_str = self.get_text(ast_member_function_name);
88
89 let resolved_expr = match (&tuple_type.0[0], &tuple_type.0[1]) {
90 (Type::Float, Type::Float) => match member_function_name_str {
91 "magnitude" => {
92 if !arguments.is_empty() {
93 return Err(self.create_err(
94 ErrorKind::WrongNumberOfArguments(arguments.len(), 0),
95 ast_member_function_name,
96 ));
97 }
98 self.create_postfix(
99 PostfixKind::IntrinsicCall(IntrinsicFunction::Float2Magnitude, vec![]),
100 &Type::Float,
101 ast_member_function_name,
102 )
103 }
104 _ => {
105 return Err(
106 self.create_err(ErrorKind::UnknownMemberFunction, ast_member_function_name)
107 );
108 }
109 },
110 _ => {
111 return Err(self.create_err(
112 ErrorKind::WrongNumberOfArguments(99, tuple_type.0.len()),
113 ast_member_function_name,
114 ));
115 }
116 };
117
118 Ok(resolved_expr)
119 }
120
121 fn check_mutable(
122 &mut self,
123 is_mutable: bool,
124 node: &swamp_script_ast::Node,
125 ) -> Result<(), Error> {
126 if !is_mutable {
127 Err(self.create_err(ErrorKind::ExpectedMutableLocation, node))
128 } else {
129 Ok(())
130 }
131 }
132
133 fn create_postfix(
134 &mut self,
135 kind: PostfixKind,
136 ty: &Type,
137 node: &swamp_script_ast::Node,
138 ) -> Postfix {
139 let resolved_node = self.to_node(node);
140
141 Postfix {
142 node: resolved_node,
143 ty: ty.clone(),
144 kind,
145 }
146 }
147
148 fn analyze_map_member_call(
149 &mut self,
150 map_type: &MapTypeRef,
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(&map_type.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: &ArrayTypeRef,
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.item_type);
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.item_type.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 =
336 { self.analyze_immutable_argument(&ast_arguments[0], &Type::Float)? };
337
338 Ok(float_expression)
339 }
340
341 fn analyze_single_int_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 expr2 = self.analyze_immutable_argument(&ast_arguments[0], &Type::Int)?;
353
354 Ok(expr2)
355 }
356
357 fn analyze_two_float_expressions(
358 &mut self,
359 node: &swamp_script_ast::Node,
360 ast_arguments: &[&swamp_script_ast::Expression],
361 ) -> Result<(Expression, Expression), Error> {
362 if ast_arguments.len() != 2 {
363 return Err(self.create_err(
364 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 2),
365 &node,
366 ));
367 }
368 let expr2 = self.analyze_immutable_argument(&ast_arguments[0], &Type::Float)?;
369 let expr3 = self.analyze_immutable_argument(&ast_arguments[1], &Type::Float)?;
370
371 Ok((expr2, expr3))
372 }
373
374 #[allow(clippy::too_many_lines)]
375 fn analyze_float_member_call(
376 &mut self,
377 ast_member_function_name: &swamp_script_ast::Node,
378 ast_arguments: &[&swamp_script_ast::Expression],
379 ) -> Result<Postfix, Error> {
380 let function_name_str = self.get_text(ast_member_function_name);
381 let node = ast_member_function_name;
382
383 let mut resulting_type = &Type::Float;
384 let kind = match function_name_str {
385 "round" => {
386 if !ast_arguments.is_empty() {
387 return Err(self.create_err(
388 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
389 &ast_member_function_name,
390 ));
391 }
392 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatRound, vec![])
393 }
394 "floor" => {
395 if !ast_arguments.is_empty() {
396 return Err(self.create_err(
397 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
398 &ast_member_function_name,
399 ));
400 }
401 resulting_type = &Type::Int;
402 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatFloor, vec![])
403 }
404 "sqrt" => {
405 if !ast_arguments.is_empty() {
406 return Err(self.create_err(
407 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
408 &ast_member_function_name,
409 ));
410 }
411 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatSqrt, vec![])
412 }
413 "sign" => {
414 if !ast_arguments.is_empty() {
415 return Err(self.create_err(
416 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
417 &ast_member_function_name,
418 ));
419 }
420 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatSign, vec![])
421 }
422 "abs" => {
423 if !ast_arguments.is_empty() {
424 return Err(self.create_err(
425 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
426 &ast_member_function_name,
427 ));
428 }
429 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatAbs, vec![])
430 }
431 "rnd" => {
432 if !ast_arguments.is_empty() {
433 return Err(self.create_err(
434 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
435 &ast_member_function_name,
436 ));
437 }
438 resulting_type = &Type::Int;
439 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatRnd, vec![])
440 }
441 "cos" => {
442 if !ast_arguments.is_empty() {
443 return Err(self.create_err(
444 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
445 &ast_member_function_name,
446 ));
447 }
448 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatCos, vec![])
449 }
450 "sin" => {
451 if !ast_arguments.is_empty() {
452 return Err(self.create_err(
453 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
454 &ast_member_function_name,
455 ));
456 }
457 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatSin, vec![])
458 }
459 "acos" => {
460 if !ast_arguments.is_empty() {
461 return Err(self.create_err(
462 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
463 &ast_member_function_name,
464 ));
465 }
466 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatAcos, vec![])
467 }
468 "asin" => {
469 if !ast_arguments.is_empty() {
470 return Err(self.create_err(
471 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
472 &ast_member_function_name,
473 ));
474 }
475 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatAsin, vec![])
476 }
477 "atan2" => {
478 let float_argument = self.analyze_single_float_expression(node, ast_arguments)?;
479 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatAtan2, vec![float_argument])
480 }
481 "min" => {
482 let float_argument = self.analyze_single_float_expression(node, ast_arguments)?;
483 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatMin, vec![float_argument])
484 }
485 "max" => {
486 let float_argument = self.analyze_single_float_expression(node, ast_arguments)?;
487 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatMax, vec![float_argument])
488 }
489 "clamp" => {
490 let (min, max) = self.analyze_two_float_expressions(node, ast_arguments)?;
491 PostfixKind::IntrinsicCall(IntrinsicFunction::FloatClamp, vec![min, max])
492 }
493 _ => {
494 return Err(
495 self.create_err(ErrorKind::UnknownMemberFunction, &ast_member_function_name)
496 );
497 }
498 };
499
500 Ok(self.create_postfix(kind, resulting_type, &ast_member_function_name))
501 }
502
503 fn analyze_string_member_call(
504 &mut self,
505 ast_member_function_name: &swamp_script_ast::Node,
506 ast_arguments: &[&swamp_script_ast::Expression],
507 ) -> Result<Postfix, Error> {
508 let function_name_str = self.get_text(ast_member_function_name);
509 let node = self.to_node(&ast_member_function_name);
510
511 match function_name_str {
512 "len" => {
513 if !ast_arguments.is_empty() {
514 return Err(self.create_err_resolved(
515 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
516 &node,
517 ));
518 }
519 Ok(self.create_postfix(
520 PostfixKind::IntrinsicCall(IntrinsicFunction::StringLen, vec![]),
521 &Type::Int,
522 ast_member_function_name,
523 ))
524 }
525 _ => Err(self.create_err(ErrorKind::UnknownMemberFunction, ast_member_function_name)),
526 }
527 }
528
529 fn analyze_int_member_call(
530 &mut self,
531 ast_member_function_name: &swamp_script_ast::Node,
532 ast_arguments: &[&swamp_script_ast::Expression],
533 ) -> Result<Postfix, Error> {
534 let function_name_str = self.get_text(ast_member_function_name);
535 let node = self.to_node(&ast_member_function_name);
536
537 let (kind, resolved_type) = match function_name_str {
538 "abs" => {
539 if !ast_arguments.is_empty() {
540 return Err(self.create_err_resolved(
541 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
542 &node,
543 ));
544 }
545 (
546 PostfixKind::IntrinsicCall(IntrinsicFunction::IntAbs, vec![]),
547 Type::Int,
548 )
549 }
550 "rnd" => {
551 if !ast_arguments.is_empty() {
552 return Err(self.create_err_resolved(
553 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
554 &node,
555 ));
556 }
557 (
558 PostfixKind::IntrinsicCall(IntrinsicFunction::IntRnd, vec![]),
559 Type::Int,
560 )
561 }
562
563 "max" => {
564 let int_argument =
565 self.analyze_single_int_expression(&ast_member_function_name, ast_arguments)?;
566 (
567 PostfixKind::IntrinsicCall(IntrinsicFunction::IntMax, vec![int_argument]),
568 Type::Int,
569 )
570 }
571
572 "min" => {
573 let int_argument =
574 self.analyze_single_int_expression(ast_member_function_name, ast_arguments)?;
575 (
576 PostfixKind::IntrinsicCall(IntrinsicFunction::IntMin, vec![int_argument]),
577 Type::Int,
578 )
579 }
580
581 "to_float" => {
582 if !ast_arguments.is_empty() {
583 return Err(self.create_err_resolved(
584 ErrorKind::WrongNumberOfArguments(ast_arguments.len(), 0),
585 &node,
586 ));
587 }
588 (
589 PostfixKind::IntrinsicCall(IntrinsicFunction::IntToFloat, vec![]),
590 Type::Float,
591 )
592 }
593 _ => {
594 return Err(
595 self.create_err(ErrorKind::UnknownMemberFunction, &ast_member_function_name)
596 );
597 }
598 };
599
600 Ok(self.create_postfix(kind, &resolved_type, ast_member_function_name))
601 }
602
603 fn check_for_internal_member_call_extra(
604 &mut self,
605 ty: &Type,
606 ast_member_function_name: &swamp_script_ast::Node,
607 ast_arguments: &[&swamp_script_ast::Expression],
608 ) -> Result<Option<Postfix>, Error> {
609 if let Type::Generic(generic_type, parameters) = ty.clone() {
611 if let Type::External(rust_type_ref) = *generic_type {
612 if rust_type_ref.as_ref().number == SPARSE_TYPE_ID {
613 if parameters.len() != 1 {
614 return Err(self.create_err(
615 ErrorKind::WrongNumberOfTypeArguments(parameters.len(), 1),
616 ast_member_function_name,
617 ));
618 }
619 let sparse_id_type = self
620 .shared
621 .lookup_table
622 .get_external_type("SparseId")
623 .expect("should have SparseId");
624 let key_type = Type::External(sparse_id_type.clone());
625 let value_type = ¶meters[0];
626 let function_name_str = self.get_text(ast_member_function_name);
627
628 let (kind, resolved_type) = match function_name_str {
630 "add" => {
631 if ast_arguments.len() != 1 {
632 return Err(self.create_err(
633 ErrorKind::WrongNumberOfTypeArguments(parameters.len(), 1),
634 ast_member_function_name,
635 ));
636 }
637 let value =
638 self.analyze_immutable_argument(&ast_arguments[0], value_type)?;
639 (
640 PostfixKind::IntrinsicCall(
641 IntrinsicFunction::SparseAdd,
642 vec![value],
643 ),
644 key_type,
645 )
646 }
647 "remove" => {
648 if ast_arguments.len() != 1 {
649 return Err(self.create_err(
650 ErrorKind::WrongNumberOfTypeArguments(parameters.len(), 1),
651 ast_member_function_name,
652 ));
653 }
654 let sparse_slot_id_expression =
655 self.analyze_immutable_argument(&ast_arguments[0], &key_type)?;
656 (
657 PostfixKind::IntrinsicCall(
658 IntrinsicFunction::SparseRemove,
659 vec![sparse_slot_id_expression],
660 ),
661 Type::Unit, )
663 }
664 _ => return Ok(None),
665 };
666
667 return Ok(Some(self.create_postfix(
668 kind,
669 &resolved_type,
670 ast_member_function_name,
671 )));
672 }
673 }
674 }
675
676 Ok(None)
677 }
678}