mod babel;
#[path = "swc_stub.rs"]
mod swc;
pub mod type_context;
pub mod swc_patterns;
pub mod swc_metadata;
pub mod decorated_ast;
pub mod swc_decorator;
pub mod swc_rewriter;
pub mod swc_hoister;
pub mod swc_emit;
pub use babel::BabelGenerator;
pub use swc::SwcGenerator;
pub use type_context::{TypeContext, TypeEnvironment, SwcTypeKind};
pub use swc_patterns::SwcPatternGenerator;
pub use swc_metadata::*;
pub use decorated_ast::*;
pub use swc_decorator::SwcDecorator;
pub use swc_rewriter::SwcRewriter;
pub use swc_hoister::SwcHoister;
pub use swc_emit::SwcEmitter;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Target {
Babel,
Swc,
Both,
}
#[derive(Debug)]
pub struct GeneratedCode {
pub babel: Option<String>,
pub swc: Option<String>,
}
#[derive(Debug)]
pub struct GeneratedCodeWithModules {
pub babel: Option<String>,
pub swc: Option<String>,
pub swc_modules: Vec<(String, String, Vec<String>, bool)>,
}
pub fn generate(program: &crate::parser::Program, target: Target) -> GeneratedCode {
let babel = if target == Target::Babel || target == Target::Both {
Some(BabelGenerator::new().generate(program))
} else {
None
};
let swc = if target == Target::Swc || target == Target::Both {
let mut decorator = SwcDecorator::new();
let decorated_program = decorator.decorate_program(program);
let mut rewriter = SwcRewriter::new();
let rewritten_program = rewriter.rewrite_program(decorated_program);
let mut emitter = SwcEmitter::new();
Some(emitter.emit_program(&rewritten_program))
} else {
None
};
GeneratedCode { babel, swc }
}
pub fn generate_with_types(
program: &crate::parser::Program,
type_env: crate::semantic::TypeEnv,
target: Target,
) -> GeneratedCode {
let result = generate_with_types_and_base_dir(program, type_env, target, std::path::PathBuf::from("."));
GeneratedCode {
babel: result.babel,
swc: result.swc,
}
}
pub fn generate_with_types_and_base_dir(
program: &crate::parser::Program,
type_env: crate::semantic::TypeEnv,
target: Target,
base_dir: std::path::PathBuf,
) -> GeneratedCodeWithModules {
let babel = if target == Target::Babel || target == Target::Both {
Some(BabelGenerator::new().generate(program))
} else {
None
};
let (swc, swc_modules) = if target == Target::Swc || target == Target::Both {
let mut decorator = SwcDecorator::with_semantic_types(type_env.clone());
let decorated_program = decorator.decorate_program(program);
let mut rewriter = SwcRewriter::new();
let rewritten_program = rewriter.rewrite_program(decorated_program);
let mut hoister = SwcHoister::new(type_env);
let hoisted_program = hoister.hoist_program(rewritten_program);
let mut emitter = SwcEmitter::with_base_dir(base_dir);
let code = emitter.emit_program(&hoisted_program);
let modules = emitter.get_imported_modules().to_vec();
let final_code = if !modules.is_empty() {
let mod_decls = emitter.generate_mod_declarations();
let use_stmts = emitter.generate_use_statements();
inject_module_imports(&code, &mod_decls, &use_stmts)
} else {
code
};
(Some(final_code), modules)
} else {
(None, Vec::new())
};
GeneratedCodeWithModules { babel, swc, swc_modules }
}
fn inject_module_imports(code: &str, mod_decls: &str, use_stmts: &str) -> String {
let lines: Vec<&str> = code.lines().collect();
let mut insert_pos = 0;
for (i, line) in lines.iter().enumerate() {
let trimmed = line.trim();
if trimmed.starts_with("use ") || trimmed.starts_with("//") || trimmed.is_empty() {
insert_pos = i + 1;
} else {
break;
}
}
let mut result = String::new();
for (i, line) in lines.iter().enumerate() {
result.push_str(line);
result.push('\n');
if i + 1 == insert_pos {
result.push_str(mod_decls);
result.push_str(use_stmts);
result.push('\n');
}
}
result
}