kotoba_rewrite/rewrite/
engine.rs

1//! 書換えエンジン
2
3use kotoba_core::{types::*, ir::*};
4use kotoba_graph::prelude::*;
5use crate::rewrite::*;
6use kotoba_core::types::Result;
7
8/// 書換えエンジン
9#[derive(Debug)]
10pub struct RewriteEngine {
11    matcher: RuleMatcher,
12    applier: RuleApplier,
13}
14
15impl RewriteEngine {
16    pub fn new() -> Self {
17        Self {
18            matcher: RuleMatcher::new(),
19            applier: RuleApplier::new(),
20        }
21    }
22
23    /// ルールをマッチングして適用
24    pub fn match_rule(&self, graph: &GraphRef, rule: &RuleIR, catalog: &Catalog) -> Result<Vec<Match>> {
25        self.matcher.find_matches(graph, rule, catalog)
26    }
27
28    /// ルールを適用してパッチを生成
29    pub fn rewrite(&self, graph: &GraphRef, rule: &RuleIR, strategy: &StrategyIR) -> Result<Patch> {
30        match &strategy.strategy {
31            StrategyOp::Once { rule: rule_name } => {
32                self.apply_once(graph, rule, rule_name)
33            }
34            StrategyOp::Exhaust { rule: rule_name, order, measure } => {
35                self.apply_exhaust(graph, rule, rule_name, order, measure.as_deref())
36            }
37            StrategyOp::While { rule: rule_name, pred, order } => {
38                self.apply_while(graph, rule, rule_name, pred, order)
39            }
40            StrategyOp::Seq { strategies } => {
41                self.apply_sequence(graph, rule, strategies)
42            }
43            StrategyOp::Choice { strategies } => {
44                self.apply_choice(graph, rule, strategies)
45            }
46            StrategyOp::Priority { strategies } => {
47                self.apply_priority(graph, rule, strategies)
48            }
49        }
50    }
51
52    /// 1回だけ適用
53    fn apply_once(&self, graph: &GraphRef, rule: &RuleIR, _rule_name: &str) -> Result<Patch> {
54        let matches = self.matcher.find_matches(graph, rule, &Catalog::empty())?;
55
56        if let Some(match_) = matches.into_iter().next() {
57            self.applier.apply_rule(graph, rule, &match_)
58        } else {
59            Ok(Patch::empty())
60        }
61    }
62
63    /// 適用可能になるまで繰り返し
64    fn apply_exhaust(&self, graph: &GraphRef, rule: &RuleIR, _rule_name: &str,
65                     order: &Order, _measure: Option<&str>) -> Result<Patch> {
66        let mut total_patch = Patch::empty();
67        let mut iteration = 0;
68        let max_iterations = 1000; // 無限ループ防止
69
70        loop {
71            let matches = self.matcher.find_matches(graph, rule, &Catalog::empty())?;
72
73            if matches.is_empty() || iteration >= max_iterations {
74                break;
75            }
76
77            // 最初のマッチを選択(orderに基づいて)
78            let match_ = self.select_match(&matches, order)?;
79
80            let patch = self.applier.apply_rule(graph, rule, &match_)?;
81            total_patch = total_patch.merge(patch);
82
83            iteration += 1;
84        }
85
86        Ok(total_patch)
87    }
88
89    /// 条件付き繰り返し
90    fn apply_while(&self, graph: &GraphRef, rule: &RuleIR, _rule_name: &str,
91                   pred: &str, order: &Order) -> Result<Patch> {
92        let mut total_patch = Patch::empty();
93
94        loop {
95            let matches = self.matcher.find_matches(graph, rule, &Catalog::empty())?;
96
97            if matches.is_empty() {
98                break;
99            }
100
101            // 述語を評価(簡易実装)
102            if !self.evaluate_predicate(pred, graph) {
103                break;
104            }
105
106            let match_ = self.select_match(&matches, order)?;
107            let patch = self.applier.apply_rule(graph, rule, &match_)?;
108            total_patch = total_patch.merge(patch);
109        }
110
111        Ok(total_patch)
112    }
113
114    /// 順次実行
115    fn apply_sequence(&self, graph: &GraphRef, rule: &RuleIR,
116                      strategies: &[Box<StrategyOp>]) -> Result<Patch> {
117        let mut total_patch = Patch::empty();
118
119        for strategy in strategies {
120            let strategy_ir = StrategyIR {
121                strategy: *strategy.clone(),
122            };
123            let patch = self.rewrite(graph, rule, &strategy_ir)?;
124            total_patch = total_patch.merge(patch);
125        }
126
127        Ok(total_patch)
128    }
129
130    /// 選択実行
131    fn apply_choice(&self, graph: &GraphRef, rule: &RuleIR,
132                    strategies: &[Box<StrategyOp>]) -> Result<Patch> {
133        for strategy in strategies {
134            let strategy_ir = StrategyIR {
135                strategy: *strategy.clone(),
136            };
137            let patch = self.rewrite(graph, rule, &strategy_ir)?;
138
139            if !patch.is_empty() {
140                return Ok(patch);
141            }
142        }
143
144        Ok(Patch::empty())
145    }
146
147    /// 優先順位付き選択
148    fn apply_priority(&self, graph: &GraphRef, rule: &RuleIR,
149                      strategies: &[PrioritizedStrategy]) -> Result<Patch> {
150        // 優先順位でソート
151        let mut sorted_strategies = strategies.to_vec();
152        sorted_strategies.sort_by_key(|s| s.priority);
153
154        for prioritized in sorted_strategies {
155            let strategy_ir = StrategyIR {
156                strategy: *prioritized.strategy,
157            };
158            let patch = self.rewrite(graph, rule, &strategy_ir)?;
159
160            if !patch.is_empty() {
161                return Ok(patch);
162            }
163        }
164
165        Ok(Patch::empty())
166    }
167
168    /// マッチを選択
169    fn select_match(&self, matches: &[Match], order: &Order) -> Result<Match> {
170        if matches.is_empty() {
171            return Err(KotobaError::Rewrite("No matches found".to_string()));
172        }
173
174        match order {
175            Order::TopDown => Ok(matches[0].clone()), // 最初のマッチ
176            Order::BottomUp => Ok(matches[matches.len() - 1].clone()), // 最後のマッチ
177            Order::Fair => Ok(matches[0].clone()), // 簡易的に最初のマッチ
178        }
179    }
180
181    /// 述語を評価
182    fn evaluate_predicate(&self, pred: &str, graph: &GraphRef) -> bool {
183        // 簡易的な述語評価(実際の実装ではRust関数を呼び出し)
184        match pred {
185            "edge_count_nonincreasing" => {
186                // エッジ数が非増加(停止測度)
187                graph.read().edge_count() <= 1000 // 仮の閾値
188            }
189            "deg_ge" => {
190                // 次数チェック(簡易版)
191                true
192            }
193            _ => true, // デフォルトでtrue
194        }
195    }
196}
197
198/// 外部関数インターフェース
199pub trait RewriteExterns {
200    fn deg_ge(&self, v: VertexId, k: u32) -> bool;
201    fn edge_count_nonincreasing(&self, g0: &GraphRef, g1: &GraphRef) -> bool;
202    fn custom_measure(&self, name: &str, args: &[Value]) -> f64;
203}