swamp_script_analyzer/
internal.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/script
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5
6use 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                //                self.check_mutable(is_mutable, ast_member_function_name)?;
179
180                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        // TODO: Early out
626        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 = &parameters[0];
642                    let function_name_str = self.get_text(ast_member_function_name);
643
644                    // TODO: Remove hack
645                    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, //Type::Optional(value_type),
678                            )
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}