rue_compiler/compile/expr/
prefix.rs

1use log::debug;
2use rue_ast::{AstNode, AstPrefixExpr};
3use rue_diagnostic::DiagnosticKind;
4use rue_hir::{Hir, UnaryOp, Value};
5use rue_parser::T;
6
7use crate::{Compiler, compile_expr};
8
9pub fn compile_prefix_expr(ctx: &mut Compiler, prefix: &AstPrefixExpr) -> Value {
10    let Some(expr) = prefix.expr() else {
11        debug!("Unresolved prefix expr");
12        return ctx.builtins().unresolved.clone();
13    };
14
15    let value = compile_expr(ctx, &expr, None);
16
17    let Some(op) = prefix.op() else {
18        return value;
19    };
20
21    match op.kind() {
22        T![!] => {
23            if ctx.is_assignable(value.ty, ctx.builtins().types.bool) {
24                let hir = ctx.alloc_hir(Hir::Unary(UnaryOp::Not, value.hir));
25                return value
26                    .flip_mappings()
27                    .with_hir(hir)
28                    .with_type(ctx.builtins().types.bool);
29            }
30        }
31        T![+] => {
32            if ctx.is_assignable(value.ty, ctx.builtins().types.int) {
33                ctx.diagnostic(prefix.syntax(), DiagnosticKind::UnnecessaryPlus);
34                return Value::new(value.hir, ctx.builtins().types.int);
35            }
36        }
37        T![-] => {
38            if ctx.is_assignable(value.ty, ctx.builtins().types.int) {
39                let hir = ctx.alloc_hir(Hir::Unary(UnaryOp::Neg, value.hir));
40                return Value::new(hir, ctx.builtins().types.int);
41            }
42        }
43        T![~] => {
44            if ctx.is_assignable(value.ty, ctx.builtins().types.int) {
45                let hir = ctx.alloc_hir(Hir::Unary(UnaryOp::BitwiseNot, value.hir));
46                return Value::new(hir, ctx.builtins().types.int);
47            }
48        }
49        _ => {}
50    }
51
52    debug!("Unresolved prefix expr due to incompatible op");
53
54    let type_name = ctx.type_name(value.ty);
55    ctx.diagnostic(
56        prefix.syntax(),
57        DiagnosticKind::IncompatibleUnaryOp(op.text().to_string(), type_name),
58    );
59    ctx.builtins().unresolved.clone()
60}