Skip to main content

luaur_analysis/methods/
constraint_generator_check_ast_expr_binary.rs

1use crate::records::constraint_generator::ConstraintGenerator;
2use crate::records::equality_constraint::EqualityConstraint;
3use crate::records::inference::Inference;
4use crate::records::type_function::TypeFunction;
5use crate::type_aliases::constraint_v::ConstraintV;
6use crate::type_aliases::scope_ptr_type::ScopePtr;
7use crate::type_aliases::type_id::TypeId;
8use alloc::vec::Vec;
9use luaur_ast::records::ast_expr::AstExpr;
10use luaur_ast::records::ast_expr_binary::AstExprBinaryOp;
11use luaur_ast::records::location::Location;
12use luaur_common::macros::luau_unreachable::LUAU_UNREACHABLE;
13
14impl ConstraintGenerator {
15    pub fn check_ast_expr_binary(
16        &mut self,
17        scope: &ScopePtr,
18        location: Location,
19        op: AstExprBinaryOp,
20        left: *mut AstExpr,
21        right: *mut AstExpr,
22        expected_type: Option<TypeId>,
23    ) -> Inference {
24        let (left_type, right_type, refinement) =
25            self.check_binary(scope, op, left, right, expected_type);
26
27        match op {
28            AstExprBinaryOp::Add => {
29                let result_type = self.create_type_function_instance(
30                    unsafe { &(*self.builtin_types).typeFunctions.add_func },
31                    Vec::from([left_type, right_type]),
32                    Vec::new(),
33                    scope,
34                    location,
35                );
36                Inference::inference_type_id_refinement_id(result_type, refinement)
37            }
38            AstExprBinaryOp::Sub => {
39                let result_type = self.create_type_function_instance(
40                    unsafe { &(*self.builtin_types).typeFunctions.sub_func },
41                    Vec::from([left_type, right_type]),
42                    Vec::new(),
43                    scope,
44                    location,
45                );
46                Inference::inference_type_id_refinement_id(result_type, refinement)
47            }
48            AstExprBinaryOp::Mul => {
49                let result_type = self.create_type_function_instance(
50                    unsafe { &(*self.builtin_types).typeFunctions.mul_func },
51                    Vec::from([left_type, right_type]),
52                    Vec::new(),
53                    scope,
54                    location,
55                );
56                Inference::inference_type_id_refinement_id(result_type, refinement)
57            }
58            AstExprBinaryOp::Div => {
59                let result_type = self.create_type_function_instance(
60                    unsafe { &(*self.builtin_types).typeFunctions.div_func },
61                    Vec::from([left_type, right_type]),
62                    Vec::new(),
63                    scope,
64                    location,
65                );
66                Inference::inference_type_id_refinement_id(result_type, refinement)
67            }
68            AstExprBinaryOp::FloorDiv => {
69                let result_type = self.create_type_function_instance(
70                    unsafe { &(*self.builtin_types).typeFunctions.idiv_func },
71                    Vec::from([left_type, right_type]),
72                    Vec::new(),
73                    scope,
74                    location,
75                );
76                Inference::inference_type_id_refinement_id(result_type, refinement)
77            }
78            AstExprBinaryOp::Pow => {
79                let result_type = self.create_type_function_instance(
80                    unsafe { &(*self.builtin_types).typeFunctions.pow_func },
81                    Vec::from([left_type, right_type]),
82                    Vec::new(),
83                    scope,
84                    location,
85                );
86                Inference::inference_type_id_refinement_id(result_type, refinement)
87            }
88            AstExprBinaryOp::Mod => {
89                let result_type = self.create_type_function_instance(
90                    unsafe { &(*self.builtin_types).typeFunctions.mod_func },
91                    Vec::from([left_type, right_type]),
92                    Vec::new(),
93                    scope,
94                    location,
95                );
96                Inference::inference_type_id_refinement_id(result_type, refinement)
97            }
98            AstExprBinaryOp::Concat => {
99                let result_type = self.create_type_function_instance(
100                    unsafe { &(*self.builtin_types).typeFunctions.concat_func },
101                    Vec::from([left_type, right_type]),
102                    Vec::new(),
103                    scope,
104                    location,
105                );
106                Inference::inference_type_id_refinement_id(result_type, refinement)
107            }
108            AstExprBinaryOp::And => {
109                let result_type = self.create_type_function_instance(
110                    unsafe { &(*self.builtin_types).typeFunctions.and_func },
111                    Vec::from([left_type, right_type]),
112                    Vec::new(),
113                    scope,
114                    location,
115                );
116                Inference::inference_type_id_refinement_id(result_type, refinement)
117            }
118            AstExprBinaryOp::Or => {
119                let result_type = self.create_type_function_instance(
120                    unsafe { &(*self.builtin_types).typeFunctions.or_func },
121                    Vec::from([left_type, right_type]),
122                    Vec::new(),
123                    scope,
124                    location,
125                );
126                Inference::inference_type_id_refinement_id(result_type, refinement)
127            }
128            AstExprBinaryOp::CompareLt
129            | AstExprBinaryOp::CompareGe
130            | AstExprBinaryOp::CompareLe
131            | AstExprBinaryOp::CompareGt => {
132                self.add_constraint_scope_ptr_location_constraint_v(
133                    scope,
134                    location,
135                    ConstraintV::Equality(EqualityConstraint {
136                        result_type: left_type,
137                        assignment_type: right_type,
138                    }),
139                );
140                Inference::inference_type_id_refinement_id(
141                    unsafe { (*self.builtin_types).booleanType },
142                    refinement,
143                )
144            }
145            AstExprBinaryOp::CompareEq | AstExprBinaryOp::CompareNe => {
146                Inference::inference_type_id_refinement_id(
147                    unsafe { (*self.builtin_types).booleanType },
148                    refinement,
149                )
150            }
151            AstExprBinaryOp::Op__Count => {
152                unsafe { (*self.ice).ice_string("Op__Count should never be generated in an AST.") };
153                LUAU_UNREACHABLE!()
154            }
155        }
156    }
157}