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::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                //if let ExpressionKind::VariableAccess(var_ref) = resolved_expr {
33                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                //}
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: &TupleTypeRef,
76        ast_member_function_name: &swamp_script_ast::Node,
77        arguments: &[&swamp_script_ast::Expression],
78    ) -> Result<Postfix, Error> {
79        //let resolved_node = self.to_node(ast_member_function_name);
80        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        // TODO: Early out
610        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 = &parameters[0];
626                    let function_name_str = self.get_text(ast_member_function_name);
627
628                    // TODO: Remove hack
629                    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, //Type::Optional(value_type),
662                            )
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}