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}