use crate::compiler::{
CompilationResult, CompilationStage, CompilationTask, CompilationUnit, Compiler, cache::CompilationCache,
codegen::CodeGenerator, context::CompilationContext, executor::Executor, ir_generator::IRGenerator, optimizer::Optimizer,
parallel::ParallelCompiler, semantic::SemanticAnalyzer,
};
use std::{collections::HashSet, path::PathBuf, sync::Arc};
use typescript_types::{TsError, TsValue};
#[derive(Debug, Clone)]
pub struct MainCompiler {
semantic_analyzer: SemanticAnalyzer,
ir_generator: IRGenerator,
optimizer: Optimizer,
code_generator: CodeGenerator,
executor: Executor,
context: CompilationContext,
cache: CompilationCache,
current_stage: CompilationStage,
}
impl MainCompiler {
pub fn new(context: CompilationContext, cache: CompilationCache) -> Self {
Self {
semantic_analyzer: SemanticAnalyzer::new(context.clone()),
ir_generator: IRGenerator::new(),
optimizer: Optimizer::new(),
code_generator: CodeGenerator::new(),
executor: Executor::new(),
context,
cache,
current_stage: CompilationStage::LexicalAnalysis,
}
}
pub fn compile_file(&mut self, path: &PathBuf) -> CompilationResult<TsValue> {
let source_content = match std::fs::read_to_string(path) {
Ok(content) => content,
Err(error) => return CompilationResult::Error(TsError::Other(error.to_string())),
};
let unit = CompilationUnit::with_path(path.to_string_lossy().to_string(), source_content);
self.compile_unit(&unit)
}
pub fn compile_unit(&mut self, unit: &CompilationUnit) -> CompilationResult<TsValue> {
let hash = CompilationCache::compute_hash(&unit.source_content);
if self.context.options.incremental {
if self.cache.is_cache_valid(&hash, &unit.dependencies.iter().cloned().collect()) {
if let Some((_, item)) = self.cache.get_cache(&hash) {
if let crate::compiler::cache::CacheItem::ExecutionResult(value) = item {
return CompilationResult::Success(*value.clone());
}
}
}
}
self.current_stage = CompilationStage::LexicalAnalysis;
self.current_stage = CompilationStage::SemanticAnalysis;
match self.semantic_analyzer.analyze(&unit.source_content) {
CompilationResult::Success(_) => {}
CompilationResult::Error(error) => return CompilationResult::Error(error),
_ => return CompilationResult::Error(TsError::Other("Semantic analysis failed".to_string())),
}
self.current_stage = CompilationStage::IRGeneration;
let ir = self.ir_generator.generate(&unit.source_content);
match ir {
CompilationResult::Success(program) => {
self.current_stage = CompilationStage::Optimization;
let optimized_ir = self.optimizer.optimize(&program);
match optimized_ir {
CompilationResult::Success(optimized_program) => {
self.current_stage = CompilationStage::CodeGeneration;
let typed_program = typescript_ir::TypedProgram::from_program(&optimized_program);
let instructions = self.code_generator.generate(&typed_program);
self.current_stage = CompilationStage::Execution;
let result = self.executor.execute(&optimized_program);
if self.context.options.incremental {
if let CompilationResult::Success(ref result) = result {
self.cache.store_cache(
&hash,
crate::compiler::cache::CacheItem::ExecutionResult(Box::new(result.clone())),
unit.dependencies.iter().cloned().collect(),
CompilationStage::Execution,
);
}
}
result
}
CompilationResult::Error(error) => CompilationResult::Error(error),
_ => CompilationResult::Error(TsError::Other("Optimization failed".to_string())),
}
}
CompilationResult::Error(error) => CompilationResult::Error(error),
_ => CompilationResult::Error(TsError::Other("IR generation failed".to_string())),
}
}
pub fn compile_files_parallel(&mut self, paths: &[PathBuf]) -> Vec<(String, CompilationResult<TsValue>)> {
paths
.iter()
.map(|path| {
let result = self.compile_file(path);
(path.to_string_lossy().to_string(), result)
})
.collect()
}
pub fn context(&self) -> &CompilationContext {
&self.context
}
pub fn context_mut(&mut self) -> &mut CompilationContext {
&mut self.context
}
pub fn cache(&self) -> &CompilationCache {
&self.cache
}
pub fn cache_mut(&mut self) -> &mut CompilationCache {
&mut self.cache
}
}
impl Compiler for MainCompiler {
fn compile(&mut self, input: &str) -> CompilationResult<TsValue> {
let unit = CompilationUnit::new(input.to_string());
self.compile_unit(&unit)
}
fn reset(&mut self) {
self.semantic_analyzer.reset();
self.ir_generator.reset();
self.optimizer.reset();
self.code_generator.reset();
self.executor.reset();
self.context = CompilationContext::default();
self.current_stage = CompilationStage::LexicalAnalysis;
}
fn current_stage(&self) -> CompilationStage {
self.current_stage
}
}
impl Default for MainCompiler {
fn default() -> Self {
Self::new(CompilationContext::default(), CompilationCache::default())
}
}