Files
hakorune/src/runner/modes/common_util/resolve/selfhost_pipeline.rs

190 lines
6.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 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())
}
}