refactor(joinir): Phase 106 Pattern2 step boxes
This commit is contained in:
@ -12,6 +12,7 @@
|
||||
use super::PolicyDecision;
|
||||
use crate::ast::{ASTNode, BinaryOperator, Span, UnaryOperator};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct LoopTrueReadDigitsPolicyResult {
|
||||
pub break_condition_node: ASTNode,
|
||||
pub allowed_ch_var: String,
|
||||
@ -59,3 +60,137 @@ pub(crate) fn classify_loop_true_read_digits(
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::ast::{BinaryOperator, LiteralValue, Span, UnaryOperator};
|
||||
|
||||
fn span() -> Span {
|
||||
Span::unknown()
|
||||
}
|
||||
|
||||
fn bool_lit(v: bool) -> ASTNode {
|
||||
ASTNode::Literal {
|
||||
value: LiteralValue::Bool(v),
|
||||
span: span(),
|
||||
}
|
||||
}
|
||||
|
||||
fn var(name: &str) -> ASTNode {
|
||||
ASTNode::Variable {
|
||||
name: name.to_string(),
|
||||
span: span(),
|
||||
}
|
||||
}
|
||||
|
||||
fn str_lit(s: &str) -> ASTNode {
|
||||
ASTNode::Literal {
|
||||
value: LiteralValue::String(s.to_string()),
|
||||
span: span(),
|
||||
}
|
||||
}
|
||||
|
||||
fn int_lit(n: i64) -> ASTNode {
|
||||
ASTNode::Literal {
|
||||
value: LiteralValue::Integer(n),
|
||||
span: span(),
|
||||
}
|
||||
}
|
||||
|
||||
fn eq(left: ASTNode, right: ASTNode) -> ASTNode {
|
||||
ASTNode::BinaryOp {
|
||||
operator: BinaryOperator::Equal,
|
||||
left: Box::new(left),
|
||||
right: Box::new(right),
|
||||
span: span(),
|
||||
}
|
||||
}
|
||||
|
||||
fn add(left: ASTNode, right: ASTNode) -> ASTNode {
|
||||
ASTNode::BinaryOp {
|
||||
operator: BinaryOperator::Add,
|
||||
left: Box::new(left),
|
||||
right: Box::new(right),
|
||||
span: span(),
|
||||
}
|
||||
}
|
||||
|
||||
fn or(left: ASTNode, right: ASTNode) -> ASTNode {
|
||||
ASTNode::BinaryOp {
|
||||
operator: BinaryOperator::Or,
|
||||
left: Box::new(left),
|
||||
right: Box::new(right),
|
||||
span: span(),
|
||||
}
|
||||
}
|
||||
|
||||
fn not(node: ASTNode) -> ASTNode {
|
||||
ASTNode::UnaryOp {
|
||||
operator: UnaryOperator::Not,
|
||||
operand: Box::new(node),
|
||||
span: span(),
|
||||
}
|
||||
}
|
||||
|
||||
fn digit_chain(var_name: &str, digits: &[&str]) -> ASTNode {
|
||||
let mut it = digits.iter();
|
||||
let first = it
|
||||
.next()
|
||||
.expect("digits must be non-empty");
|
||||
let mut acc = eq(var(var_name), str_lit(first));
|
||||
for d in it {
|
||||
acc = or(acc, eq(var(var_name), str_lit(d)));
|
||||
}
|
||||
acc
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_digits_loop_true_policy_returns_break_when_true_and_allowlist() {
|
||||
// loop(true) {
|
||||
// if ch == "" { break }
|
||||
// if is_digit(ch) { out = out + ch; i = i + 1 } else { break }
|
||||
// }
|
||||
let condition = bool_lit(true);
|
||||
|
||||
let eos_cond = eq(var("ch"), str_lit(""));
|
||||
let digit_cond = digit_chain(
|
||||
"ch",
|
||||
&["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
|
||||
);
|
||||
|
||||
let body = vec![
|
||||
ASTNode::If {
|
||||
condition: Box::new(eos_cond.clone()),
|
||||
then_body: vec![ASTNode::Break { span: span() }],
|
||||
else_body: None,
|
||||
span: span(),
|
||||
},
|
||||
ASTNode::If {
|
||||
condition: Box::new(digit_cond.clone()),
|
||||
then_body: vec![
|
||||
ASTNode::Assignment {
|
||||
target: Box::new(var("out")),
|
||||
value: Box::new(add(var("out"), var("ch"))),
|
||||
span: span(),
|
||||
},
|
||||
ASTNode::Assignment {
|
||||
target: Box::new(var("i")),
|
||||
value: Box::new(add(var("i"), int_lit(1))),
|
||||
span: span(),
|
||||
},
|
||||
],
|
||||
else_body: Some(vec![ASTNode::Break { span: span() }]),
|
||||
span: span(),
|
||||
},
|
||||
];
|
||||
|
||||
let decision = classify_loop_true_read_digits(&condition, &body);
|
||||
let result = match decision {
|
||||
PolicyDecision::Use(v) => v,
|
||||
other => panic!("expected PolicyDecision::Use, got {:?}", other),
|
||||
};
|
||||
|
||||
assert_eq!(result.allowed_ch_var, "ch");
|
||||
assert_eq!(result.break_condition_node, or(eos_cond, not(digit_cond)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user