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); }
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); 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 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 }; 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}