Skip to main content

vm/
binary.rs

1use super::{JITRunTime, context::BuildContext};
2use cranelift::prelude::*;
3use dynamic::{Dynamic, Type};
4use parser::{BinaryOp, Expr};
5
6use anyhow::{Result, anyhow};
7
8impl JITRunTime {
9    fn strcat(&mut self, ctx: &mut BuildContext, left: Value, right: Value) -> Result<Value> {
10        let fn_id = self.strcat_fn.ok_or_else(|| anyhow!("VM strcat runtime is not registered"))?;
11        let fn_ref = self.get_fn_ref(ctx, fn_id);
12        let call_inst = ctx.builder.ins().call(fn_ref, &[left, right]);
13        Ok(ctx.builder.inst_results(call_inst)[0])
14    }
15
16    fn strcat_i64(&mut self, ctx: &mut BuildContext, left: Value, right: Value) -> Result<Value> {
17        let fn_id = self.strcat_i64_fn.ok_or_else(|| anyhow!("VM strcat i64 runtime is not registered"))?;
18        let fn_ref = self.get_fn_ref(ctx, fn_id);
19        let call_inst = ctx.builder.ins().call(fn_ref, &[left, right]);
20        Ok(ctx.builder.inst_results(call_inst)[0])
21    }
22
23    fn strcat_assign(&mut self, ctx: &mut BuildContext, left: Value, right: Value) -> Result<Value> {
24        let fn_id = self.strcat_assign_fn.ok_or_else(|| anyhow!("VM strcat assign runtime is not registered"))?;
25        let fn_ref = self.get_fn_ref(ctx, fn_id);
26        let call_inst = ctx.builder.ins().call(fn_ref, &[left, right]);
27        Ok(ctx.builder.inst_results(call_inst)[0])
28    }
29
30    fn any_to_string(&mut self, ctx: &mut BuildContext, vt: (Value, Type)) -> Result<Value> {
31        let value = self.convert(ctx, vt, Type::Any)?;
32        self.call(ctx, self.get_method(&Type::Any, "to_string")?, vec![value]).map(|(v, _)| v)
33    }
34
35    fn any_logic(&mut self, ctx: &mut BuildContext, left: Value, op: BinaryOp, right: Value) -> Result<(Value, Type)> {
36        let op = ctx.builder.ins().iconst(types::I32, i32::from(op) as i64);
37        self.call(ctx, self.get_method(&Type::Any, "logic")?, vec![left, op, right])
38    }
39
40    fn any_binary(&mut self, ctx: &mut BuildContext, left: Value, op: BinaryOp, right: Value) -> Result<(Value, Type)> {
41        let op = ctx.builder.ins().iconst(types::I32, i32::from(op) as i64);
42        self.call(ctx, self.get_method(&Type::Any, "binary")?, vec![left, op, right])
43    }
44
45    fn struct_to_dynamic(&mut self, ctx: &mut BuildContext, base: Value, ty: &Type) -> Result<Value> {
46        let Type::Struct { params: _, fields: _ } = ty else {
47            return Err(anyhow!("不是结构体 {:?}", ty));
48        };
49        let ty_ptr = Self::type_ptr_const(ctx, ty);
50        let fn_id = self.struct_from_ptr_fn.ok_or_else(|| anyhow!("VM struct Dynamic runtime is not registered"))?;
51        let fn_ref = self.get_fn_ref(ctx, fn_id);
52        let call_inst = ctx.builder.ins().call(fn_ref, &[base, ty_ptr]);
53        Ok(ctx.builder.inst_results(call_inst)[0])
54    }
55
56    fn array_to_dynamic(&mut self, ctx: &mut BuildContext, base: Value, ty: &Type) -> Result<Value> {
57        let Type::Array(_, _) = ty else {
58            return Err(anyhow!("不是数组 {:?}", ty));
59        };
60        let ty_ptr = Self::type_ptr_const(ctx, ty);
61        let fn_id = self.array_from_ptr_fn.ok_or_else(|| anyhow!("VM array Dynamic runtime is not registered"))?;
62        let fn_ref = self.get_fn_ref(ctx, fn_id);
63        let call_inst = ctx.builder.ins().call(fn_ref, &[base, ty_ptr]);
64        Ok(ctx.builder.inst_results(call_inst)[0])
65    }
66
67    pub(crate) fn bool_value(&mut self, ctx: &mut BuildContext, vt: (Value, Type)) -> Result<Value> {
68        if vt.1.is_bool() {
69            Ok(vt.0)
70        } else if vt.1.is_any() {
71            self.call(ctx, self.get_method(&Type::Any, "to_bool")?, vec![vt.0]).map(|(v, _)| v)
72        } else if vt.1.is_int() || vt.1.is_uint() {
73            Ok(ctx.builder.ins().icmp_imm(IntCC::NotEqual, vt.0, 0))
74        } else if vt.1.is_f32() {
75            let zero = ctx.builder.ins().f32const(0.0);
76            Ok(ctx.builder.ins().fcmp(FloatCC::NotEqual, vt.0, zero))
77        } else if vt.1.is_f64() {
78            let zero = ctx.builder.ins().f64const(0.0);
79            Ok(ctx.builder.ins().fcmp(FloatCC::NotEqual, vt.0, zero))
80        } else {
81            Err(anyhow!("cannot convert {:?} to bool", vt.1))
82        }
83    }
84
85    pub fn convert(&mut self, ctx: &mut BuildContext, vt: (Value, Type), ty: Type) -> Result<Value> {
86        let vt = if matches!(vt.1, Type::Symbol { .. }) {
87            let resolved = self.compiler.symbols.get_type(&vt.1).unwrap_or_else(|_| vt.1.clone());
88            (vt.0, resolved)
89        } else {
90            vt
91        };
92        if vt.1 != ty {
93            if ty.is_any() {
94                if self.is_opaque_custom_ty(&vt.1) {
95                    return Ok(vt.0);
96                } else if vt.1.is_array() {
97                    return self.array_to_dynamic(ctx, vt.0, &vt.1);
98                } else if vt.1.is_struct() {
99                    return self.struct_to_dynamic(ctx, vt.0, &vt.1);
100                } else if vt.1.is_bool() {
101                    return self.call(ctx, self.get_method(&Type::Any, "from_bool")?, vec![vt.0]).map(|(v, _)| v);
102                } else if vt.1.is_uint() {
103                    let v = if vt.1.width() < 8 { ctx.builder.ins().uextend(types::I64, vt.0) } else { vt.0 };
104                    return self.call(ctx, self.get_method(&Type::Any, "from_i64")?, vec![v]).map(|(v, _)| v);
105                } else if vt.1.is_int() {
106                    let v = if vt.1.width() < 8 { ctx.builder.ins().sextend(types::I64, vt.0) } else { vt.0 };
107                    return self.call(ctx, self.get_method(&Type::Any, "from_i64")?, vec![v]).map(|(v, _)| v);
108                } else if vt.1.is_f32() {
109                    let v = ctx.builder.ins().fpromote(types::F64, vt.0);
110                    return self.call(ctx, self.get_method(&Type::Any, "from_f64")?, vec![v]).map(|(v, _)| v);
111                } else if vt.1.is_f64() {
112                    return self.call(ctx, self.get_method(&Type::Any, "from_f64")?, vec![vt.0]).map(|(v, _)| v);
113                } else if vt.1.is_str() {
114                    return Ok(vt.0);
115                } else if matches!(vt.1, Type::Map | Type::List(_) | Type::Iter) {
116                    return Ok(vt.0);
117                } else if matches!(vt.1, Type::Symbol { .. }) {
118                    return Ok(vt.0);
119                }
120            } else if vt.1.is_any() {
121                if ty.is_bool() {
122                    return self.call(ctx, self.get_method(&Type::Any, "to_bool")?, vec![vt.0]).map(|(v, _)| v);
123                } else if ty.is_array() {
124                    return self.any_to_array(ctx, vt.0, &ty);
125                } else if ty.is_str() {
126                    return self.call(ctx, self.get_method(&Type::Any, "to_string")?, vec![vt.0]).map(|(v, _)| v);
127                } else if ty.is_int() | ty.is_uint() {
128                    let (v, _) = self.call(ctx, self.get_method(&Type::Any, "to_i64")?, vec![vt.0])?;
129                    return Ok(match ty.width() {
130                        1 => ctx.builder.ins().ireduce(types::I8, v),
131                        2 => ctx.builder.ins().ireduce(types::I16, v),
132                        4 => ctx.builder.ins().ireduce(types::I32, v),
133                        _ => v,
134                    });
135                } else if ty.is_f32() {
136                    let v = self.call(ctx, self.get_method(&Type::Any, "to_f64")?, vec![vt.0]).map(|(v, _)| v)?;
137                    return Ok(ctx.builder.ins().fdemote(types::F32, v));
138                } else if ty.is_f64() {
139                    return self.call(ctx, self.get_method(&Type::Any, "to_f64")?, vec![vt.0]).map(|(v, _)| v);
140                } else {
141                    return Ok(vt.0);
142                }
143            } else if ty.is_str() {
144                return self.any_to_string(ctx, vt);
145            } else if ty.is_int() || ty.is_uint() {
146                if vt.1.is_f32() || vt.1.is_f64() {
147                    let target = crate::get_type(&ty)?;
148                    if ty.is_uint() {
149                        return Ok(ctx.builder.ins().fcvt_to_uint(target, vt.0));
150                    } else if ty.is_int() {
151                        return Ok(ctx.builder.ins().fcvt_to_sint(target, vt.0));
152                    }
153                }
154                if vt.1.is_int() || vt.1.is_uint() || vt.1.is_bool() {
155                    let target = crate::get_type(&ty)?;
156                    let actual = ctx.builder.func.dfg.value_type(vt.0);
157                    if actual == target {
158                        return Ok(vt.0);
159                    }
160                    if actual.is_int() && target.is_int() {
161                        if actual.bits() > target.bits() {
162                            return Ok(ctx.builder.ins().ireduce(target, vt.0));
163                        }
164                        if actual.bits() < target.bits() {
165                            return if vt.1.is_int() { Ok(ctx.builder.ins().sextend(target, vt.0)) } else { Ok(ctx.builder.ins().uextend(target, vt.0)) };
166                        }
167                    }
168                }
169                if vt.1.is_str() {
170                    let (v, _) = self.call(ctx, self.get_method(&Type::Any, "to_i64")?, vec![vt.0])?;
171                    return Ok(match ty.width() {
172                        1 => ctx.builder.ins().ireduce(types::I8, v),
173                        2 => ctx.builder.ins().ireduce(types::I16, v),
174                        4 => ctx.builder.ins().ireduce(types::I32, v),
175                        _ => v,
176                    });
177                }
178            } else if ty.is_f32() {
179                if vt.1.is_int() {
180                    return Ok(ctx.builder.ins().fcvt_from_sint(types::F32, vt.0));
181                } else if vt.1.is_uint() {
182                    return Ok(ctx.builder.ins().fcvt_from_uint(types::F32, vt.0));
183                } else if vt.1.is_f64() {
184                    return Ok(ctx.builder.ins().fdemote(types::F32, vt.0));
185                } else if vt.1.is_str() {
186                    let v = self.call(ctx, self.get_method(&Type::Any, "to_f64")?, vec![vt.0]).map(|(v, _)| v)?;
187                    return Ok(ctx.builder.ins().fdemote(types::F32, v));
188                }
189            } else if ty.is_f64() {
190                if vt.1.is_int() {
191                    return Ok(ctx.builder.ins().fcvt_from_sint(types::F64, vt.0));
192                } else if vt.1.is_uint() {
193                    return Ok(ctx.builder.ins().fcvt_from_uint(types::F64, vt.0));
194                } else if vt.1.is_f32() {
195                    return Ok(ctx.builder.ins().fpromote(types::F64, vt.0));
196                } else if vt.1.is_str() {
197                    return self.call(ctx, self.get_method(&Type::Any, "to_f64")?, vec![vt.0]).map(|(v, _)| v);
198                }
199            } else if let Type::Symbol { id: _, params: _ } = ty {
200                log::debug!("convert {:?} -> {:?}", vt, ty);
201                return Ok(vt.0); //结构类型 可以看作 External 类型
202            }
203            if vt.1.is_bool() {
204                let v = ctx.builder.ins().sextend(types::I64, vt.0);
205                return self.call(ctx, self.get_method(&Type::Any, "from_i64")?, vec![v]).map(|(v, _)| v);
206            }
207            log::error!("未实现 {:?} {:?}", vt, ty); //暂时还没有实现 struct 的 初始化
208            Ok(vt.0)
209        } else {
210            Ok(vt.0)
211        }
212    }
213
214    pub(crate) fn binary_with_expected(&mut self, ctx: &mut BuildContext, left: (Value, Type), op: BinaryOp, right: &Expr, expected: Option<&Type>) -> Result<(Value, Type)> {
215        //处理可以计算的简单情形
216        if matches!(op, BinaryOp::And | BinaryOp::Or) {
217            return self.short_circuit_logic(ctx, left, op, right);
218        }
219        let right_ty_hint = if right.is_value() { right.clone().value().ok().map(|v| v.get_type()) } else { self.get_dynamic(right).map(|v| v.get_type()) };
220        let right = if right.is_value() {
221            let right = right.clone().value()?;
222            if right.is_f32() {
223                (ctx.builder.ins().f32const(right.as_float().unwrap() as f32), Type::F32)
224            } else if right.is_f64() {
225                (ctx.builder.ins().f64const(right.as_float().unwrap() as f64), Type::F64)
226            } else if left.1.is_any() {
227                if right.is_int() {
228                    (ctx.builder.ins().iconst(types::I64, right.as_int().unwrap()), Type::I64)
229                } else if right.is_null() {
230                    self.call(ctx, self.get_method(&Type::Any, "null")?, vec![])?
231                } else {
232                    ctx.get_const(&right)?
233                }
234            } else {
235                return self.binary_imm(ctx, left, op, right);
236            }
237        } else {
238            self.eval(ctx, right)?.get(ctx).ok_or_else(|| anyhow!("没有返回值: {:?}", right))?
239        };
240        let right_ty = right_ty_hint.as_ref().unwrap_or(&right.1);
241        let numeric_expected = expected.filter(|ty| (ty.is_int() || ty.is_uint() || ty.is_float()) && (left.1.is_any() || right.1.is_any()));
242        let ty = if (op.is_add() || op.is_logic()) && (left.1.is_str() || right.1.is_str() || right_ty.is_str()) {
243            Type::Str
244        } else if !op.is_logic()
245            && let Some(expected) = numeric_expected
246        {
247            expected.clone()
248        } else if (op.is_add() || op.is_logic()) && (left.1.is_any() || right.1.is_any()) {
249            Type::Any
250        } else {
251            left.1.clone() + right.1.clone()
252        }; //为了支持字符串的加法需要单独处理
253        if ty.is_str() && op.is_add() {
254            if op == BinaryOp::AddAssign {
255                let left = self.convert(ctx, left, Type::Any)?;
256                let right = self.convert(ctx, right, Type::Any)?;
257                return Ok((self.strcat_assign(ctx, left, right)?, ty));
258            }
259            if left.1.is_str() && right.1.is_str() {
260                return Ok((self.strcat(ctx, left.0, right.0)?, Type::Str));
261            }
262            if left.1.is_str() && right.1.is_int() {
263                let right = self.convert(ctx, right, Type::I64)?;
264                return Ok((self.strcat_i64(ctx, left.0, right)?, Type::Str));
265            }
266            let left = self.convert(ctx, left, Type::Any)?;
267            let right = self.convert(ctx, right, Type::Any)?;
268            let result = self.any_binary(ctx, left, op, right)?.0;
269            return Ok((result, ty));
270        }
271        let left = self.convert(ctx, left, ty.clone())?;
272        let right = self.convert(ctx, right, ty.clone())?;
273        if ty.is_any() {
274            if op.is_logic() {
275                return self.any_logic(ctx, left, op, right);
276            } else {
277                return self.any_binary(ctx, left, op, right);
278            }
279        }
280        if ty.is_str() && op.is_logic() {
281            return self.any_logic(ctx, left, op, right);
282        }
283        match op {
284            BinaryOp::Add | BinaryOp::AddAssign => {
285                if ty.is_int() || ty.is_uint() {
286                    return Ok((ctx.builder.ins().iadd(left, right), ty));
287                } else if ty.is_float() {
288                    return Ok((ctx.builder.ins().fadd(left, right), ty));
289                } else if ty.is_str() {
290                    let result = self.any_binary(ctx, left, op, right)?.0;
291                    return Ok((result, ty));
292                }
293            }
294            BinaryOp::Sub | BinaryOp::SubAssign => {
295                if ty.is_int() || ty.is_uint() {
296                    return Ok((ctx.builder.ins().isub(left, right), ty));
297                } else if ty.is_float() {
298                    return Ok((ctx.builder.ins().fsub(left, right), ty));
299                }
300            }
301            BinaryOp::Mul | BinaryOp::MulAssign => {
302                if ty.is_int() || ty.is_uint() {
303                    return Ok((ctx.builder.ins().imul(left, right), ty));
304                } else if ty.is_float() {
305                    return Ok((ctx.builder.ins().fmul(left, right), ty));
306                }
307            }
308            BinaryOp::Div | BinaryOp::DivAssign => {
309                if ty.is_int() {
310                    return Ok((ctx.builder.ins().sdiv(left, right), ty));
311                } else if ty.is_uint() {
312                    return Ok((ctx.builder.ins().udiv(left, right), ty));
313                } else if ty.is_float() {
314                    return Ok((ctx.builder.ins().fdiv(left, right), ty));
315                }
316            }
317            BinaryOp::Mod | BinaryOp::ModAssign => {
318                if ty.is_int() {
319                    return Ok((ctx.builder.ins().srem(left, right), ty));
320                } else if ty.is_uint() {
321                    return Ok((ctx.builder.ins().urem(left, right), ty));
322                }
323            }
324            BinaryOp::Shl | BinaryOp::ShlAssign => {
325                if ty.is_int() || ty.is_uint() {
326                    return Ok((ctx.builder.ins().ishl(left, right), ty));
327                }
328            }
329            BinaryOp::Shr | BinaryOp::ShrAssign => {
330                if ty.is_int() {
331                    return Ok((ctx.builder.ins().sshr(left, right), ty));
332                } else if ty.is_uint() {
333                    return Ok((ctx.builder.ins().ushr(left, right), ty));
334                }
335            }
336            BinaryOp::BitAnd | BinaryOp::BitAndAssign => {
337                return Ok((ctx.builder.ins().band(left, right), ty));
338            }
339            BinaryOp::BitOr | BinaryOp::BitOrAssign => {
340                return Ok((ctx.builder.ins().bor(left, right), ty));
341            }
342            BinaryOp::BitXor | BinaryOp::BitXorAssign => {
343                return Ok((ctx.builder.ins().bxor(left, right), ty));
344            }
345            BinaryOp::Eq => {
346                if ty.is_int() | ty.is_uint() || ty.is_bool() {
347                    return Ok((ctx.builder.ins().icmp(IntCC::Equal, left, right), Type::Bool));
348                } else if ty.is_float() {
349                    return Ok((ctx.builder.ins().fcmp(FloatCC::Equal, left, right), Type::Bool));
350                }
351            }
352            BinaryOp::Ne => {
353                if ty.is_int() | ty.is_uint() || ty.is_bool() {
354                    return Ok((ctx.builder.ins().icmp(IntCC::NotEqual, left, right), Type::Bool));
355                } else if ty.is_float() {
356                    return Ok((ctx.builder.ins().fcmp(FloatCC::NotEqual, left, right), Type::Bool));
357                }
358            }
359            BinaryOp::Lt => {
360                if ty.is_int() {
361                    return Ok((ctx.builder.ins().icmp(IntCC::SignedLessThan, left, right), Type::Bool));
362                } else if ty.is_uint() {
363                    return Ok((ctx.builder.ins().icmp(IntCC::UnsignedLessThan, left, right), Type::Bool));
364                } else if ty.is_float() {
365                    return Ok((ctx.builder.ins().fcmp(FloatCC::LessThan, left, right), Type::Bool));
366                }
367            }
368            BinaryOp::Le => {
369                if ty.is_int() {
370                    return Ok((ctx.builder.ins().icmp(IntCC::SignedLessThanOrEqual, left, right), Type::Bool));
371                } else if ty.is_uint() {
372                    return Ok((ctx.builder.ins().icmp(IntCC::UnsignedLessThanOrEqual, left, right), Type::Bool));
373                } else if ty.is_float() {
374                    return Ok((ctx.builder.ins().fcmp(FloatCC::LessThanOrEqual, left, right), Type::Bool));
375                }
376            }
377            BinaryOp::Gt => {
378                if ty.is_int() {
379                    return Ok((ctx.builder.ins().icmp(IntCC::SignedGreaterThan, left, right), Type::Bool));
380                } else if ty.is_uint() {
381                    return Ok((ctx.builder.ins().icmp(IntCC::UnsignedGreaterThan, left, right), Type::Bool));
382                } else if ty.is_float() {
383                    return Ok((ctx.builder.ins().fcmp(FloatCC::GreaterThan, left, right), Type::Bool));
384                }
385            }
386            BinaryOp::Ge => {
387                if ty.is_int() {
388                    return Ok((ctx.builder.ins().icmp(IntCC::SignedGreaterThanOrEqual, left, right), Type::Bool));
389                } else if ty.is_uint() {
390                    return Ok((ctx.builder.ins().icmp(IntCC::UnsignedGreaterThanOrEqual, left, right), Type::Bool));
391                } else if ty.is_float() {
392                    return Ok((ctx.builder.ins().fcmp(FloatCC::GreaterThanOrEqual, left, right), Type::Bool));
393                }
394            }
395            _ => {}
396        }
397        panic!("未实现 {:?} {:?} {:?} {:?}", left, op, right, ty)
398    }
399
400    pub(crate) fn binary_imm<'a>(&mut self, ctx: &'a mut BuildContext, left: (Value, Type), op: BinaryOp, right: Dynamic) -> Result<(Value, Type)> {
401        let ty = left.1.clone() + right.get_type();
402        let bool_imm = || right.as_bool().map(|value| if value { 1 } else { 0 });
403        if ty.is_str() && op.is_add() {
404            if op == BinaryOp::AddAssign {
405                let left = self.convert(ctx, left, Type::Any)?;
406                let right_vt = ctx.get_const(&right).or_else(|_| {
407                    let idx = self.compiler.get_const(right.clone());
408                    self.get_const_value(ctx, idx)
409                })?;
410                let right = self.convert(ctx, right_vt, Type::Any)?;
411                return Ok((self.strcat_assign(ctx, left, right)?, ty));
412            }
413            if left.1.is_str() && right.is_str() {
414                let right_vt = ctx.get_const(&right).or_else(|_| {
415                    let idx = self.compiler.get_const(right.clone());
416                    self.get_const_value(ctx, idx)
417                })?;
418                let right = self.convert(ctx, right_vt, Type::Str)?;
419                return Ok((self.strcat(ctx, left.0, right)?, Type::Str));
420            }
421            if left.1.is_str() && right.is_int() {
422                let right = ctx.get_const(&right)?;
423                let right = self.convert(ctx, right, Type::I64)?;
424                return Ok((self.strcat_i64(ctx, left.0, right)?, Type::Str));
425            }
426            let left = self.convert(ctx, left, Type::Any)?;
427            let right_vt = ctx.get_const(&right).or_else(|_| {
428                let idx = self.compiler.get_const(right.clone());
429                self.get_const_value(ctx, idx)
430            })?;
431            let right = self.convert(ctx, right_vt, Type::Any)?;
432            let result = self.any_binary(ctx, left, op, right)?.0;
433            return Ok((result, ty));
434        }
435        let left = self.convert(ctx, left, ty.clone())?;
436        if ty.is_str() && op.is_logic() {
437            let right_vt = ctx.get_const(&right).or_else(|_| {
438                let idx = self.compiler.get_const(right.clone());
439                self.get_const_value(ctx, idx)
440            })?;
441            let right = self.convert(ctx, right_vt, Type::Str)?;
442            return self.any_logic(ctx, left, op, right);
443        }
444        let right_float = if ty.is_float() {
445            let right = right.as_float().ok_or(anyhow!("非数字"))?;
446            Some(if ty.is_f32() { ctx.builder.ins().f32const(right as f32) } else { ctx.builder.ins().f64const(right) })
447        } else {
448            None
449        };
450        match op {
451            BinaryOp::Add | BinaryOp::AddAssign => {
452                if ty.is_str() {
453                    let right_vt = ctx.get_const(&right).or_else(|_| {
454                        let idx = self.compiler.get_const(right.clone());
455                        self.get_const_value(ctx, idx)
456                    })?;
457                    let right = self.convert(ctx, right_vt, Type::Str)?;
458                    let result = self.any_binary(ctx, left, op, right)?.0;
459                    return Ok((result, ty));
460                }
461                if ty.is_int() | ty.is_uint() {
462                    return Ok((ctx.builder.ins().iadd_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
463                } else if ty.is_float() {
464                    return Ok((ctx.builder.ins().fadd(left, right_float.unwrap()), ty));
465                }
466            }
467            BinaryOp::Sub | BinaryOp::SubAssign => {
468                if ty.is_int() | ty.is_uint() {
469                    return Ok((ctx.builder.ins().iadd_imm(left, -right.as_int().ok_or(anyhow!("非整数"))?), ty));
470                } else if ty.is_float() {
471                    return Ok((ctx.builder.ins().fsub(left, right_float.unwrap()), ty));
472                }
473            }
474            BinaryOp::Mul | BinaryOp::MulAssign => {
475                if ty.is_int() | ty.is_uint() {
476                    return Ok((ctx.builder.ins().imul_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
477                } else if ty.is_float() {
478                    return Ok((ctx.builder.ins().fmul(left, right_float.unwrap()), ty));
479                }
480            }
481            BinaryOp::Div | BinaryOp::DivAssign => {
482                if ty.is_int() {
483                    return Ok((ctx.builder.ins().sdiv_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
484                } else if ty.is_uint() {
485                    return Ok((ctx.builder.ins().udiv_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
486                } else if ty.is_float() {
487                    return Ok((ctx.builder.ins().fdiv(left, right_float.unwrap()), ty));
488                }
489            }
490            BinaryOp::Shl | BinaryOp::ShlAssign => {
491                if ty.is_int() || ty.is_uint() {
492                    return Ok((ctx.builder.ins().ishl_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
493                }
494            }
495            BinaryOp::Shr | BinaryOp::ShrAssign => {
496                if ty.is_int() {
497                    return Ok((ctx.builder.ins().sshr_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
498                } else if ty.is_uint() {
499                    return Ok((ctx.builder.ins().ushr_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
500                }
501            }
502            BinaryOp::BitAnd | BinaryOp::BitAndAssign => {
503                return Ok((ctx.builder.ins().band_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
504            }
505            BinaryOp::BitOr | BinaryOp::BitOrAssign => {
506                return Ok((ctx.builder.ins().bor_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
507            }
508            BinaryOp::BitXor | BinaryOp::BitXorAssign => {
509                return Ok((ctx.builder.ins().bxor_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
510            }
511            BinaryOp::Eq => {
512                if ty.is_int() | ty.is_uint() {
513                    return Ok((ctx.builder.ins().icmp_imm(IntCC::Equal, left, right.as_int().unwrap()), Type::Bool));
514                } else if ty.is_bool() {
515                    return Ok((ctx.builder.ins().icmp_imm(IntCC::Equal, left, bool_imm().unwrap()), Type::Bool));
516                } else if ty.is_float() {
517                    return Ok((ctx.builder.ins().fcmp(FloatCC::Equal, left, right_float.unwrap()), Type::Bool));
518                }
519            }
520            BinaryOp::Ne => {
521                if ty.is_int() | ty.is_uint() {
522                    return Ok((ctx.builder.ins().icmp_imm(IntCC::NotEqual, left, right.as_int().unwrap()), Type::Bool));
523                } else if ty.is_bool() {
524                    return Ok((ctx.builder.ins().icmp_imm(IntCC::NotEqual, left, bool_imm().unwrap()), Type::Bool));
525                } else if ty.is_float() {
526                    return Ok((ctx.builder.ins().fcmp(FloatCC::NotEqual, left, right_float.unwrap()), Type::Bool));
527                }
528            }
529            BinaryOp::Le => {
530                if ty.is_int() {
531                    return Ok((ctx.builder.ins().icmp_imm(IntCC::SignedLessThanOrEqual, left, right.as_int().unwrap()), Type::Bool));
532                } else if ty.is_uint() {
533                    return Ok((ctx.builder.ins().icmp_imm(IntCC::UnsignedLessThanOrEqual, left, right.as_int().unwrap()), Type::Bool));
534                } else if ty.is_float() {
535                    return Ok((ctx.builder.ins().fcmp(FloatCC::LessThanOrEqual, left, right_float.unwrap()), Type::Bool));
536                }
537            }
538            BinaryOp::Lt => {
539                if ty.is_int() {
540                    return Ok((ctx.builder.ins().icmp_imm(IntCC::SignedLessThan, left, right.as_int().unwrap()), Type::Bool));
541                } else if ty.is_uint() {
542                    return Ok((ctx.builder.ins().icmp_imm(IntCC::UnsignedLessThan, left, right.as_int().unwrap()), Type::Bool));
543                } else if ty.is_float() {
544                    return Ok((ctx.builder.ins().fcmp(FloatCC::LessThan, left, right_float.unwrap()), Type::Bool));
545                }
546            }
547            BinaryOp::Ge => {
548                if ty.is_int() {
549                    return Ok((ctx.builder.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, left, right.as_int().unwrap()), Type::Bool));
550                } else if ty.is_uint() {
551                    return Ok((ctx.builder.ins().icmp_imm(IntCC::UnsignedGreaterThanOrEqual, left, right.as_int().unwrap()), Type::Bool));
552                } else if ty.is_float() {
553                    return Ok((ctx.builder.ins().fcmp(FloatCC::GreaterThanOrEqual, left, right_float.unwrap()), Type::Bool));
554                }
555            }
556            BinaryOp::Gt => {
557                if ty.is_int() {
558                    return Ok((ctx.builder.ins().icmp_imm(IntCC::SignedGreaterThan, left, right.as_int().unwrap()), Type::Bool));
559                } else if ty.is_uint() {
560                    return Ok((ctx.builder.ins().icmp_imm(IntCC::UnsignedGreaterThan, left, right.as_int().unwrap()), Type::Bool));
561                } else if ty.is_float() {
562                    return Ok((ctx.builder.ins().fcmp(FloatCC::GreaterThan, left, right_float.unwrap()), Type::Bool));
563                }
564            }
565            BinaryOp::Mod | BinaryOp::ModAssign => {
566                if ty.is_int() {
567                    return Ok((ctx.builder.ins().srem_imm(left, right.as_int().unwrap()), ty));
568                } else if ty.is_uint() {
569                    return Ok((ctx.builder.ins().urem_imm(left, right.as_int().unwrap()), ty));
570                }
571            }
572            exp => {
573                panic!("不支持的操作 {:?}", exp)
574            }
575        }
576        panic!("未实现 {:?} {:?} {:?}", ty, op, right.get_type())
577    }
578}