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