|
| 1 | +use core::sync::atomic::{AtomicU64, Ordering}; |
| 2 | + |
1 | 3 | use smallvec::SmallVec; |
2 | 4 |
|
3 | 5 | use crate::error::{expect_function_argument_amount, expect_operator_argument_amount}; |
@@ -605,38 +607,60 @@ fn compile_special_function<F: EvalexprFloat>( |
605 | 607 | })))); |
606 | 608 | Ok(CompileNativeResult::Compiled) |
607 | 609 | }, |
608 | | - "if" | "If" => match node.children.len() { |
609 | | - 2 => { |
610 | | - let true_expr = node.children.pop().unwrap(); |
611 | | - let condition = node.children.pop().unwrap(); |
612 | | - compile_to_flat_inner(condition, ops)?; |
613 | | - ops.push(FlatOperator::If { |
614 | | - true_expr: Box::new(ClosureNode::Unprepared { |
615 | | - params: SmallVec::new(), |
616 | | - expr: compile_to_flat(true_expr)?, |
617 | | - }), |
618 | | - false_expr: None, |
619 | | - }); |
620 | | - Ok(CompileNativeResult::Compiled) |
621 | | - }, |
622 | | - 3 => { |
623 | | - let false_expr = node.children.pop().unwrap(); |
624 | | - let true_expr = node.children.pop().unwrap(); |
625 | | - let condition = node.children.pop().unwrap(); |
626 | | - compile_to_flat_inner(condition, ops)?; |
627 | | - ops.push(FlatOperator::If { |
628 | | - true_expr: Box::new(ClosureNode::Unprepared { |
629 | | - params: SmallVec::new(), |
630 | | - expr: compile_to_flat(true_expr)?, |
631 | | - }), |
632 | | - false_expr: Some(Box::new(ClosureNode::Unprepared { |
633 | | - params: SmallVec::new(), |
634 | | - expr: compile_to_flat(false_expr)?, |
635 | | - })), |
636 | | - }); |
637 | | - Ok(CompileNativeResult::Compiled) |
638 | | - }, |
639 | | - _ => Err(EvalexprError::wrong_function_argument_amount_range(0, 2..=3)), |
| 610 | + "if" | "If" => { |
| 611 | + static LABEL_ID: AtomicU64 = AtomicU64::new(0); |
| 612 | + |
| 613 | + match node.children.len() { |
| 614 | + 2 => { |
| 615 | + let true_expr = node.children.pop().unwrap(); |
| 616 | + let condition = node.children.pop().unwrap(); |
| 617 | + compile_to_flat_inner(condition, ops)?; |
| 618 | + let l1 = LABEL_ID.fetch_add(1, Ordering::Relaxed); |
| 619 | + let l2 = LABEL_ID.fetch_add(1, Ordering::Relaxed); |
| 620 | + ops.push(FlatOperator::JumpIfFalse { id: l1 , offset:None}); |
| 621 | + compile_to_flat_inner(true_expr, ops)?; |
| 622 | + ops.push(FlatOperator::Jump { id: l2 , offset:None}); |
| 623 | + ops.push(FlatOperator::Label { id: l1 }); |
| 624 | + ops.push(FlatOperator::PushConst { value: Value::Empty }); |
| 625 | + ops.push(FlatOperator::Label { id: l2 }); |
| 626 | + |
| 627 | + // ops.push(FlatOperator::If { |
| 628 | + // true_expr: Box::new(ClosureNode::Unprepared { |
| 629 | + // params: SmallVec::new(), |
| 630 | + // expr: compile_to_flat(true_expr)?, |
| 631 | + // }), |
| 632 | + // false_expr: None, |
| 633 | + // }); |
| 634 | + Ok(CompileNativeResult::Compiled) |
| 635 | + }, |
| 636 | + 3 => { |
| 637 | + let false_expr = node.children.pop().unwrap(); |
| 638 | + let true_expr = node.children.pop().unwrap(); |
| 639 | + let condition = node.children.pop().unwrap(); |
| 640 | + compile_to_flat_inner(condition, ops)?; |
| 641 | + let l1 = LABEL_ID.fetch_add(1, Ordering::Relaxed); |
| 642 | + let l2 = LABEL_ID.fetch_add(1, Ordering::Relaxed); |
| 643 | + ops.push(FlatOperator::JumpIfFalse { id: l1 , offset:None}); |
| 644 | + compile_to_flat_inner(true_expr, ops)?; |
| 645 | + ops.push(FlatOperator::Jump { id: l2 , offset:None}); |
| 646 | + ops.push(FlatOperator::Label { id: l1 }); |
| 647 | + compile_to_flat_inner(false_expr, ops)?; |
| 648 | + ops.push(FlatOperator::Label { id: l2 }); |
| 649 | + |
| 650 | + // ops.push(FlatOperator::If { |
| 651 | + // true_expr: Box::new(ClosureNode::Unprepared { |
| 652 | + // params: SmallVec::new(), |
| 653 | + // expr: compile_to_flat(true_expr)?, |
| 654 | + // }), |
| 655 | + // false_expr: Some(Box::new(ClosureNode::Unprepared { |
| 656 | + // params: SmallVec::new(), |
| 657 | + // expr: compile_to_flat(false_expr)?, |
| 658 | + // })), |
| 659 | + // }); |
| 660 | + Ok(CompileNativeResult::Compiled) |
| 661 | + }, |
| 662 | + _ => Err(EvalexprError::wrong_function_argument_amount_range(0, 2..=3)), |
| 663 | + } |
640 | 664 | }, |
641 | 665 | _ => Ok(CompileNativeResult::NotNative(node)), |
642 | 666 | } |
|
0 commit comments