Skip to content

Commit f82adcf

Browse files
committed
rework if operators to use jumps instead of exprs. also fold boolean operators.
1 parent e87d823 commit f82adcf

10 files changed

Lines changed: 590 additions & 441 deletions

File tree

evalexpr/src/flat_node/compile.rs

Lines changed: 56 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use core::sync::atomic::{AtomicU64, Ordering};
2+
13
use smallvec::SmallVec;
24

35
use crate::error::{expect_function_argument_amount, expect_operator_argument_amount};
@@ -605,38 +607,60 @@ fn compile_special_function<F: EvalexprFloat>(
605607
}))));
606608
Ok(CompileNativeResult::Compiled)
607609
},
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+
}
640664
},
641665
_ => Ok(CompileNativeResult::NotNative(node)),
642666
}

0 commit comments

Comments
 (0)