swamp_script_analyzer/
operator.rs1use crate::err::{Error, ErrorKind};
7use crate::{Analyzer, TypeContext};
8use swamp_script_semantic::{BinaryOperator, BinaryOperatorKind, UnaryOperator, UnaryOperatorKind};
9use swamp_script_types::prelude::*;
10use tracing::debug;
11
12impl Analyzer<'_> {
13 pub(crate) fn analyze_binary_op(
14 &mut self,
15 ast_left: &swamp_script_ast::Expression,
16 ast_op: &swamp_script_ast::BinaryOperator,
17 ast_right: &swamp_script_ast::Expression,
18 ) -> Result<(BinaryOperator, Type), Error> {
19 let anything_context = TypeContext::new_anything_argument();
20 let left = self.analyze_expression(ast_left, &anything_context)?;
21 let left_type = left.ty.clone();
22
23 let right = self.analyze_expression(ast_right, &anything_context)?;
24 let right_type = right.ty.clone();
25
26 let kind = self.convert_binary_operator_kind(ast_op);
27 let node = self.to_node(&ast_op.node);
28
29 match (&kind, &left_type, &right_type) {
30 (&BinaryOperatorKind::Add, Type::String, _) => Ok((
32 BinaryOperator {
33 left: Box::new(left),
34 right: Box::new(right),
35 kind,
36 node,
37 },
38 Type::String,
39 )),
40
41 (
43 BinaryOperatorKind::Equal
44 | BinaryOperatorKind::NotEqual
45 | BinaryOperatorKind::GreaterThan
46 | BinaryOperatorKind::GreaterEqual
47 | BinaryOperatorKind::LessThan
48 | BinaryOperatorKind::LessEqual,
49 _,
50 _,
51 ) => {
52 if !left_type.compatible_with(&right_type) {
53 debug!(?left_type, ?right_type, "type mismatch in comparison");
54 return Err(self.create_err(
55 ErrorKind::IncompatibleTypes {
56 expected: left_type,
57 found: right_type,
58 },
59 &ast_op.node,
60 ));
61 }
62 Ok((
63 BinaryOperator {
64 left: Box::new(left),
65 right: Box::new(right),
66 kind,
67 node,
68 },
69 Type::Bool,
70 ))
71 }
72
73 _ => {
75 if !left_type.compatible_with(&right_type) {
76 debug!(?left_type, ?right_type, "type mismatch in operation");
77 return Err(self.create_err_resolved(
78 ErrorKind::IncompatibleTypes {
79 expected: left_type,
80 found: right_type,
81 },
82 &node,
83 ));
84 }
85 Ok((
86 BinaryOperator {
87 left: Box::new(left),
88 right: Box::new(right),
89 kind,
90 node,
91 },
92 left_type,
93 ))
94 }
95 }
96 }
97
98 pub(crate) fn analyze_unary_op(
99 &mut self,
100 ast_op: &swamp_script_ast::UnaryOperator,
101 ast_left: &swamp_script_ast::Expression,
102 ) -> Result<(UnaryOperator, Type), Error> {
103 let (node, kind, require_type) = match ast_op {
104 swamp_script_ast::UnaryOperator::Not(node) => {
105 (node, UnaryOperatorKind::Not, Some(&Type::Bool))
106 }
107 swamp_script_ast::UnaryOperator::Negate(node) => {
108 (node, UnaryOperatorKind::Negate, None)
109 }
110 };
111 let context = TypeContext::new_unsure_argument(require_type);
112 let left = self.analyze_expression(ast_left, &context)?;
113 let resolved_type = left.ty.clone();
114 Ok((
115 UnaryOperator {
116 left: Box::new(left),
117 kind,
118 node: self.to_node(node),
119 },
120 resolved_type,
121 ))
122 }
123
124 const fn convert_binary_operator_kind(
125 &self,
126 binary_operator: &swamp_script_ast::BinaryOperator,
127 ) -> BinaryOperatorKind {
128 match binary_operator.kind {
129 swamp_script_ast::BinaryOperatorKind::Add => BinaryOperatorKind::Add,
130 swamp_script_ast::BinaryOperatorKind::Subtract => BinaryOperatorKind::Subtract,
131 swamp_script_ast::BinaryOperatorKind::Multiply => BinaryOperatorKind::Multiply,
132 swamp_script_ast::BinaryOperatorKind::Divide => BinaryOperatorKind::Divide,
133 swamp_script_ast::BinaryOperatorKind::Modulo => BinaryOperatorKind::Modulo,
134 swamp_script_ast::BinaryOperatorKind::LogicalOr => BinaryOperatorKind::LogicalOr,
135 swamp_script_ast::BinaryOperatorKind::LogicalAnd => BinaryOperatorKind::LogicalAnd,
136 swamp_script_ast::BinaryOperatorKind::Equal => BinaryOperatorKind::Equal,
137 swamp_script_ast::BinaryOperatorKind::NotEqual => BinaryOperatorKind::NotEqual,
138 swamp_script_ast::BinaryOperatorKind::LessThan => BinaryOperatorKind::LessThan,
139 swamp_script_ast::BinaryOperatorKind::LessEqual => BinaryOperatorKind::LessEqual,
140 swamp_script_ast::BinaryOperatorKind::GreaterThan => BinaryOperatorKind::GreaterThan,
141 swamp_script_ast::BinaryOperatorKind::GreaterEqual => BinaryOperatorKind::GreaterEqual,
142 swamp_script_ast::BinaryOperatorKind::RangeExclusive => {
143 BinaryOperatorKind::RangeExclusive
144 }
145 }
146 }
147}