190 lines
6.5 KiB
Rust
190 lines
6.5 KiB
Rust
//! Selfhost Pipeline Box - 綺麗綺麗なセルフホストパイプライン専門家!📦
|
||
//!
|
||
//! セルフホストコンパイルの複雑な処理を箱に閉じ込めて、
|
||
//! 保守性とテスト容易性を向上させるにゃ!
|
||
|
||
use crate::runner::NyashRunner;
|
||
use crate::runner::modes::common_util::resolve::prelude_manager::{PreludeManagerBox, MergeStrategy};
|
||
|
||
/// 📦 SelfhostPipelineBox - セルフホストパイプラインの専門家!
|
||
///
|
||
/// コンパイラーパイプライン全体を管理する箱にゃ!
|
||
pub struct SelfhostPipelineBox<'a> {
|
||
runner: &'a NyashRunner,
|
||
prelude_manager: PreludeManagerBox<'a>,
|
||
}
|
||
|
||
/// 🎯 CompilationResult - コンパイル結果!
|
||
#[derive(Debug)]
|
||
pub struct CompilationResult {
|
||
pub success: bool,
|
||
pub final_code: String,
|
||
pub merge_strategy: MergeStrategy,
|
||
pub prelude_count: usize,
|
||
pub processing_time_ms: u64,
|
||
}
|
||
|
||
/// ⚙️ PipelineConfig - パイプライン設定!
|
||
#[derive(Debug, Clone)]
|
||
pub struct PipelineConfig {
|
||
pub enable_using: bool,
|
||
pub enable_ast_merge: bool,
|
||
pub trace_execution: bool,
|
||
pub debug_mode: bool,
|
||
}
|
||
|
||
impl<'a> SelfhostPipelineBox<'a> {
|
||
/// 🌟 新しいSelfhostPipelineBoxを作るにゃ!
|
||
pub fn new(runner: &'a NyashRunner) -> Self {
|
||
let prelude_manager = PreludeManagerBox::new(runner);
|
||
|
||
Self {
|
||
runner,
|
||
prelude_manager,
|
||
}
|
||
}
|
||
|
||
/// 🚀 セルフホストパイプラインを実行するにゃ!
|
||
pub fn execute_pipeline(
|
||
&mut self,
|
||
code: &str,
|
||
filename: &str,
|
||
) -> Result<CompilationResult, String> {
|
||
let start_time = std::time::Instant::now();
|
||
let config = self.build_config();
|
||
|
||
// usingが無効ならそのまま返す
|
||
if !config.enable_using {
|
||
return Ok(CompilationResult {
|
||
success: true,
|
||
final_code: code.to_string(),
|
||
merge_strategy: MergeStrategy::Text, // デフォルト
|
||
prelude_count: 0,
|
||
processing_time_ms: start_time.elapsed().as_millis() as u64,
|
||
});
|
||
}
|
||
|
||
// 第1フェーズ:using文解析とプレリュードパス収集
|
||
let (cleaned_main, prelude_paths) = self.collect_and_resolve_using(code, filename)?;
|
||
|
||
// 第2フェーズ:プレリュード統合
|
||
let merge_result = if config.enable_ast_merge {
|
||
self.prelude_manager.merge_ast(&cleaned_main, filename, &prelude_paths)?
|
||
} else {
|
||
self.prelude_manager.merge_text(&cleaned_main, filename, &prelude_paths)?
|
||
};
|
||
|
||
let processing_time = start_time.elapsed().as_millis() as u64;
|
||
|
||
Ok(CompilationResult {
|
||
success: true,
|
||
final_code: merge_result.merged_content,
|
||
merge_strategy: merge_result.strategy,
|
||
prelude_count: merge_result.prelude_count,
|
||
processing_time_ms: processing_time,
|
||
})
|
||
}
|
||
|
||
/// 📋 パイプライン設定を構築するにゃ!
|
||
fn build_config(&self) -> PipelineConfig {
|
||
PipelineConfig {
|
||
enable_using: crate::config::env::enable_using(),
|
||
enable_ast_merge: crate::config::env::using_ast_enabled(),
|
||
trace_execution: std::env::var("NYASH_RESOLVE_TRACE").ok().as_deref() == Some("1"),
|
||
debug_mode: std::env::var("NYASH_RESOLVE_SEAM_DEBUG").ok().as_deref() == Some("1"),
|
||
}
|
||
}
|
||
|
||
/// 🔍 using文を収集して解決するにゃ!
|
||
fn collect_and_resolve_using(
|
||
&mut self,
|
||
code: &str,
|
||
filename: &str,
|
||
) -> Result<(String, Vec<String>), String> {
|
||
// 既存のresolve_prelude_paths_profiledを使用
|
||
crate::runner::modes::common_util::resolve::strip::resolve_prelude_paths_profiled(
|
||
&self.runner,
|
||
code,
|
||
filename,
|
||
)
|
||
}
|
||
|
||
/// 📊 パイプライン統計を表示するにゃ!
|
||
pub fn print_pipeline_stats(&self, result: &CompilationResult) {
|
||
let strategy_str = match result.merge_strategy {
|
||
MergeStrategy::Text => "text",
|
||
MergeStrategy::Ast => "ast",
|
||
};
|
||
|
||
eprintln!(
|
||
"[selfhost-pipeline] ✅ Completed in {}ms (strategy: {}, preludes: {})",
|
||
result.processing_time_ms,
|
||
strategy_str,
|
||
result.prelude_count
|
||
);
|
||
}
|
||
|
||
/// 🚨 エラーハンドリングとフォールバックするにゃ!
|
||
pub fn handle_fallback(
|
||
&self,
|
||
error: &str,
|
||
original_code: &str,
|
||
filename: &str,
|
||
) -> CompilationResult {
|
||
eprintln!("[selfhost-pipeline] ⚠️ Error: {}", error);
|
||
eprintln!("[selfhost-pipeline] 🔄 Falling back to original code");
|
||
|
||
CompilationResult {
|
||
success: false,
|
||
final_code: original_code.to_string(),
|
||
merge_strategy: MergeStrategy::Text, // フォールバックはテキスト
|
||
prelude_count: 0,
|
||
processing_time_ms: 0,
|
||
}
|
||
}
|
||
|
||
/// 🧪 パイプラインを検証するにゃ!(テスト用)
|
||
pub fn validate_pipeline(&self, code: &str, filename: &str) -> Result<Vec<String>, String> {
|
||
let mut issues = Vec::new();
|
||
|
||
// usingシステムの検証
|
||
if crate::config::env::enable_using() {
|
||
// using文があるかチェック
|
||
let using_count = code.lines()
|
||
.filter(|line| line.trim().starts_with("using "))
|
||
.count();
|
||
|
||
if using_count > 0 {
|
||
// プレリュード解決を試みる
|
||
match crate::runner::modes::common_util::resolve::strip::resolve_prelude_paths_profiled(
|
||
&self.runner,
|
||
code,
|
||
filename,
|
||
) {
|
||
Ok((_, paths)) => {
|
||
if paths.is_empty() {
|
||
issues.push("using statements found but no preludes resolved".to_string());
|
||
}
|
||
}
|
||
Err(e) => {
|
||
issues.push(format!("using resolution failed: {}", e));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Ok(issues)
|
||
}
|
||
|
||
/// 📊 パフォーマンスプロファイリングするにゃ!
|
||
pub fn profile_pipeline(
|
||
&mut self,
|
||
code: &str,
|
||
filename: &str,
|
||
) -> Result<String, String> {
|
||
// プロファイル機能を実装(別途)
|
||
// TODO: プロファイル機能を追加
|
||
Err("Profiling not yet implemented".to_string())
|
||
}
|
||
}
|