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            "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        // TODO: Early out
609        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 = &parameters[0];
625                    let function_name_str = self.get_text(ast_member_function_name);
626
627                    // TODO: Remove hack
628                    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, //Type::Optional(value_type),
661                            )
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}