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