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 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        // TODO: Early out
606        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 = &parameters[0];
622                    let function_name_str = self.get_text(ast_member_function_name);
623
624                    // TODO: Remove hack
625                    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, //Type::Optional(value_type),
658                            )
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}