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(left_type, right_type),
56 &ast_op.node,
57 ));
58 }
59 Ok((
60 BinaryOperator {
61 left: Box::new(left),
62 right: Box::new(right),
63 kind,
64 node,
65 },
66 Type::Bool,
67 ))
68 }
69
70 _ => {
72 if !left_type.compatible_with(&right_type) {
73 debug!(?left_type, ?right_type, "type mismatch in operation");
74 return Err(self.create_err_resolved(
75 ErrorKind::IncompatibleTypes(left_type, right_type),
76 &node,
77 ));
78 }
79 Ok((
80 BinaryOperator {
81 left: Box::new(left),
82 right: Box::new(right),
83 kind,
84 node,
85 },
86 left_type,
87 ))
88 }
89 }
90 }
91
92 pub(crate) fn analyze_unary_op(
93 &mut self,
94 ast_op: &swamp_script_ast::UnaryOperator,
95 ast_left: &swamp_script_ast::Expression,
96 ) -> Result<(UnaryOperator, Type), Error> {
97 let (node, kind, require_type) = match ast_op {
98 swamp_script_ast::UnaryOperator::Not(node) => {
99 (node, UnaryOperatorKind::Not, Some(&Type::Bool))
100 }
101 swamp_script_ast::UnaryOperator::Negate(node) => {
102 (node, UnaryOperatorKind::Negate, None)
103 }
104 };
105 let context = TypeContext::new_unsure_argument(require_type);
106 let left = self.analyze_expression(ast_left, &context)?;
107 let resolved_type = left.ty.clone();
108 Ok((
109 UnaryOperator {
110 left: Box::new(left),
111 kind,
112 node: self.to_node(node),
113 },
114 resolved_type,
115 ))
116 }
117
118 const fn convert_binary_operator_kind(
119 &self,
120 binary_operator: &swamp_script_ast::BinaryOperator,
121 ) -> BinaryOperatorKind {
122 match binary_operator.kind {
123 swamp_script_ast::BinaryOperatorKind::Add => BinaryOperatorKind::Add,
124 swamp_script_ast::BinaryOperatorKind::Subtract => BinaryOperatorKind::Subtract,
125 swamp_script_ast::BinaryOperatorKind::Multiply => BinaryOperatorKind::Multiply,
126 swamp_script_ast::BinaryOperatorKind::Divide => BinaryOperatorKind::Divide,
127 swamp_script_ast::BinaryOperatorKind::Modulo => BinaryOperatorKind::Modulo,
128 swamp_script_ast::BinaryOperatorKind::LogicalOr => BinaryOperatorKind::LogicalOr,
129 swamp_script_ast::BinaryOperatorKind::LogicalAnd => BinaryOperatorKind::LogicalAnd,
130 swamp_script_ast::BinaryOperatorKind::Equal => BinaryOperatorKind::Equal,
131 swamp_script_ast::BinaryOperatorKind::NotEqual => BinaryOperatorKind::NotEqual,
132 swamp_script_ast::BinaryOperatorKind::LessThan => BinaryOperatorKind::LessThan,
133 swamp_script_ast::BinaryOperatorKind::LessEqual => BinaryOperatorKind::LessEqual,
134 swamp_script_ast::BinaryOperatorKind::GreaterThan => BinaryOperatorKind::GreaterThan,
135 swamp_script_ast::BinaryOperatorKind::GreaterEqual => BinaryOperatorKind::GreaterEqual,
136 swamp_script_ast::BinaryOperatorKind::RangeExclusive => {
137 BinaryOperatorKind::RangeExclusive
138 }
139 }
140 }
141}