1use crate::{
6 interpreter::evaluator::Evaluator,
7 interpreter::values::Value,
8 lexer::tokentypes::TokenType,
9 utils::{errors::Error, span::Span},
10};
11
12impl Evaluator {
13 fn type_mismatch_binary(
14 &self,
15 op: &str,
16 left: &Value,
17 left_span: Span,
18 right: &Value,
19 right_span: Span,
20 span: Span,
21 ) -> Error {
22 self.err(format!("type mismatch on {}", op), span)
23 .with_label(left_span, format!("this is {}", left.type_name()))
24 .with_label(right_span, format!("this is {}", right.type_name()))
25 }
26
27 pub fn match_binary_operator(
28 &mut self,
29 left: Value,
30 left_span: Span,
31 right: Value,
32 right_span: Span,
33 operator: &TokenType,
34 span: Span,
35 ) -> Result<Value, Error> {
36 let v = match operator {
37 TokenType::Plus => match (&left, &right) {
38 (Value::Integer(a), Value::Integer(b)) => Value::Integer(a + b),
39 (Value::Float(a), Value::Float(b)) => Value::Float(a + b),
40 (Value::Byte(a), Value::Byte(b)) => Value::Byte(a + b),
41
42 _ => {
43 return Err(
44 self.type_mismatch_binary("+", &left, left_span, &right, right_span, span)
45 );
46 }
47 },
48 TokenType::Minus => match (&left, &right) {
49 (Value::Integer(a), Value::Integer(b)) => Value::Integer(a - b),
50 (Value::Float(a), Value::Float(b)) => Value::Float(a - b),
51 (Value::Byte(a), Value::Byte(b)) => Value::Byte(a - b),
52
53 _ => {
54 return Err(
55 self.type_mismatch_binary("-", &left, left_span, &right, right_span, span)
56 );
57 }
58 },
59 TokenType::Star => match (&left, &right) {
60 (Value::Integer(a), Value::Integer(b)) => Value::Integer(a * b),
61 (Value::Float(a), Value::Float(b)) => Value::Float(a * b),
62 (Value::Byte(a), Value::Byte(b)) => Value::Byte(a * b),
63
64 _ => {
65 return Err(
66 self.type_mismatch_binary("*", &left, left_span, &right, right_span, span)
67 );
68 }
69 },
70 TokenType::Slash => match (&left, &right) {
71 (Value::Integer(a), Value::Integer(b)) => {
72 if *b == 0 {
73 return Err(self.err("division by zero", span));
74 }
75 Value::Integer(a / b)
76 }
77 (Value::Float(a), Value::Float(b)) => Value::Float(a / b),
78 (Value::Byte(a), Value::Byte(b)) => {
79 if *b == 0 {
80 return Err(self.err("division by zero", span));
81 }
82 Value::Byte(a / b)
83 }
84
85 _ => {
86 return Err(
87 self.type_mismatch_binary("/", &left, left_span, &right, right_span, span)
88 );
89 }
90 },
91 TokenType::Less => match (&left, &right) {
92 (Value::Integer(a), Value::Integer(b)) => Value::Bool(a < b),
93 (Value::Float(a), Value::Float(b)) => Value::Bool(a < b),
94 (Value::Byte(a), Value::Byte(b)) => Value::Bool(a < b),
95 _ => {
96 return Err(
97 self.type_mismatch_binary("<", &left, left_span, &right, right_span, span)
98 );
99 }
100 },
101 TokenType::Greater => match (&left, &right) {
102 (Value::Integer(a), Value::Integer(b)) => Value::Bool(a > b),
103 (Value::Float(a), Value::Float(b)) => Value::Bool(a > b),
104 (Value::Byte(a), Value::Byte(b)) => Value::Bool(a > b),
105 _ => {
106 return Err(
107 self.type_mismatch_binary(">", &left, left_span, &right, right_span, span)
108 );
109 }
110 },
111 TokenType::LessEqual => match (&left, &right) {
112 (Value::Integer(a), Value::Integer(b)) => Value::Bool(a <= b),
113 (Value::Float(a), Value::Float(b)) => Value::Bool(a <= b),
114 (Value::Byte(a), Value::Byte(b)) => Value::Bool(a <= b),
115 _ => {
116 return Err(
117 self.type_mismatch_binary("<=", &left, left_span, &right, right_span, span)
118 );
119 }
120 },
121 TokenType::GreaterEqual => match (&left, &right) {
122 (Value::Integer(a), Value::Integer(b)) => Value::Bool(a >= b),
123 (Value::Float(a), Value::Float(b)) => Value::Bool(a >= b),
124 (Value::Byte(a), Value::Byte(b)) => Value::Bool(a >= b),
125 _ => {
126 return Err(
127 self.type_mismatch_binary(">=", &left, left_span, &right, right_span, span)
128 );
129 }
130 },
131 TokenType::BangEqual => match (&left, &right) {
132 (Value::Integer(a), Value::Integer(b)) => Value::Bool(a != b),
133 (Value::Float(a), Value::Float(b)) => Value::Bool(a != b),
134 (Value::String(a), Value::String(b)) => Value::Bool(a != b),
135 (Value::Char(a), Value::Char(b)) => Value::Bool(a != b),
136 (Value::Bool(a), Value::Bool(b)) => Value::Bool(a != b),
137 (Value::Byte(a), Value::Byte(b)) => Value::Bool(a != b),
138 (
139 Value::Enum {
140 name: a_name,
141 variant: a_var,
142 },
143 Value::Enum {
144 name: b_name,
145 variant: b_var,
146 },
147 ) => Value::Bool(a_name != b_name || a_var != b_var),
148 _ => {
149 return Err(
150 self.type_mismatch_binary("!=", &left, left_span, &right, right_span, span)
151 );
152 }
153 },
154 TokenType::Compare => match (&left, &right) {
155 (Value::Integer(a), Value::Integer(b)) => Value::Bool(a == b),
156 (Value::Float(a), Value::Float(b)) => Value::Bool(a == b),
157 (Value::String(a), Value::String(b)) => Value::Bool(a == b),
158 (Value::Char(a), Value::Char(b)) => Value::Bool(a == b),
159 (Value::Bool(a), Value::Bool(b)) => Value::Bool(a == b),
160 (Value::Byte(a), Value::Byte(b)) => Value::Bool(a == b),
161 (
162 Value::Enum {
163 name: a_name,
164 variant: a_var,
165 },
166 Value::Enum {
167 name: b_name,
168 variant: b_var,
169 },
170 ) => Value::Bool(a_name == b_name && a_var == b_var),
171 _ => {
172 return Err(
173 self.type_mismatch_binary("==", &left, left_span, &right, right_span, span)
174 );
175 }
176 },
177 _ => return Err(self.err("unknown binary operator", span)),
178 };
179 Ok(v)
180 }
181}