rl_lang/checker/operators/
binary.rs1use crate::{
18 ast::statements::TypeAnnotation,
19 checker::{
20 operators::op_str,
21 structs::{CheckType, TypeChecker},
22 },
23 lexer::tokentypes::TokenType,
24 utils::span::Span,
25};
26
27impl TypeChecker {
28 pub fn check_binary_operator(
29 &mut self,
30 left: CheckType,
31 right: CheckType,
32 op: &TokenType,
33 span: Span,
34 ) -> CheckType {
35 if left.is_unknown() || right.is_unknown() {
37 return CheckType::Unknown;
38 }
39
40 match op {
41 TokenType::Plus | TokenType::Minus | TokenType::Star | TokenType::Slash => {
43 match (&left, &right) {
44 (
45 CheckType::Known(TypeAnnotation::Int | TypeAnnotation::CInt),
46 CheckType::Known(TypeAnnotation::Int | TypeAnnotation::CInt),
47 ) => CheckType::Known(TypeAnnotation::Int),
48 (
49 CheckType::Known(TypeAnnotation::Float | TypeAnnotation::CFloat),
50 CheckType::Known(TypeAnnotation::Float | TypeAnnotation::CFloat),
51 ) => CheckType::Known(TypeAnnotation::Float),
52 (
53 CheckType::Known(TypeAnnotation::Byte | TypeAnnotation::CByte),
54 CheckType::Known(TypeAnnotation::Byte | TypeAnnotation::CByte),
55 ) => CheckType::Known(TypeAnnotation::Byte),
56
57 _ => {
58 self.error(
59 format!(
60 "type mismatch on {}: got {} and {}",
61 op_str(op),
62 left.info(),
63 right.info()
64 ),
65 span,
66 );
67 CheckType::Unknown
68 }
69 }
70 }
71
72 TokenType::Less
74 | TokenType::Greater
75 | TokenType::LessEqual
76 | TokenType::GreaterEqual => match (&left, &right) {
77 (
78 CheckType::Known(TypeAnnotation::Int | TypeAnnotation::CInt),
79 CheckType::Known(TypeAnnotation::Int | TypeAnnotation::CInt),
80 )
81 | (
82 CheckType::Known(TypeAnnotation::Float | TypeAnnotation::CFloat),
83 CheckType::Known(TypeAnnotation::Float | TypeAnnotation::CFloat),
84 ) => CheckType::Known(TypeAnnotation::Bool),
85 (
86 CheckType::Known(TypeAnnotation::Byte | TypeAnnotation::CByte),
87 CheckType::Known(TypeAnnotation::Byte | TypeAnnotation::CByte),
88 ) => CheckType::Known(TypeAnnotation::Bool),
89
90 _ => {
91 self.error(
92 format!(
93 "type mismatch on {}: got {} and {}",
94 op_str(op),
95 left.info(),
96 right.info()
97 ),
98 span,
99 );
100 CheckType::Unknown
101 }
102 },
103
104 TokenType::Compare | TokenType::BangEqual => {
106 let ok = matches!(
107 (&left, &right),
108 (
109 CheckType::Known(TypeAnnotation::Int | TypeAnnotation::CInt),
110 CheckType::Known(TypeAnnotation::Int | TypeAnnotation::CInt),
111 ) | (
112 CheckType::Known(TypeAnnotation::Byte | TypeAnnotation::CByte),
113 CheckType::Known(TypeAnnotation::Byte | TypeAnnotation::CByte),
114 ) | (
115 CheckType::Known(TypeAnnotation::Float | TypeAnnotation::CFloat),
116 CheckType::Known(TypeAnnotation::Float | TypeAnnotation::CFloat),
117 ) | (
118 CheckType::Known(TypeAnnotation::String | TypeAnnotation::CString),
119 CheckType::Known(TypeAnnotation::String | TypeAnnotation::CString),
120 ) | (
121 CheckType::Known(TypeAnnotation::Char | TypeAnnotation::CChar),
122 CheckType::Known(TypeAnnotation::Char | TypeAnnotation::CChar),
123 ) | (
124 CheckType::Known(TypeAnnotation::Bool | TypeAnnotation::CBool),
125 CheckType::Known(TypeAnnotation::Bool | TypeAnnotation::CBool),
126 ) | (
127 CheckType::Known(TypeAnnotation::Enum(_) | TypeAnnotation::CEnum(_)),
128 CheckType::Known(TypeAnnotation::Enum(_) | TypeAnnotation::CEnum(_)),
129 ) | (
130 CheckType::Known(TypeAnnotation::Record(_) | TypeAnnotation::CRecord(_)),
131 CheckType::Known(TypeAnnotation::Record(_) | TypeAnnotation::CRecord(_)),
132 )
133 );
134 if !ok {
135 self.error(
136 format!(
137 "type mismatch on {}: got {} and {}",
138 op_str(op),
139 left.info(),
140 right.info()
141 ),
142 span,
143 );
144 }
145 CheckType::Known(TypeAnnotation::Bool)
146 }
147
148 TokenType::And | TokenType::Or => {
149 if !matches!(
150 left,
151 CheckType::Known(TypeAnnotation::Bool | TypeAnnotation::CBool)
152 ) {
153 self.error(
154 format!("expected bool on the left side of {}", op_str(op)),
155 span,
156 );
157 }
158 if !matches!(
159 right,
160 CheckType::Known(TypeAnnotation::Bool | TypeAnnotation::CBool)
161 ) {
162 self.error(
163 format!("expected bool on the right side of {}", op_str(op)),
164 span,
165 );
166 }
167
168 CheckType::Known(TypeAnnotation::Bool)
169 }
170
171 _ => {
173 self.error(format!("unknown binary operator {:?}", op), span);
174 CheckType::Unknown
175 }
176 }
177 }
178}